Split Vilya into core and aslib submodules.
This ensures that our ActionScript artifact is properly published to Maven Central for all to use. I'm still putting off creating vilya-tools. Later, later...
This commit is contained in:
+110
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.threerings</groupId>
|
||||
<artifactId>vilya-parent</artifactId>
|
||||
<version>1.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>vilyalib</artifactId>
|
||||
<packaging>swc</packaging>
|
||||
<name>Vilya ActionScript</name>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>flexlib-repo</id>
|
||||
<url>http://maven.ow2.org/maven2</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>ooo-ext-maven-repo</id>
|
||||
<url>http://ooo-maven.googlecode.com/hg/repository</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>ooo-maven-repo</id>
|
||||
<url>http://threerings.github.com/maven-repo</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<flex.version>4.1.0.16076</flex.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.threerings</groupId>
|
||||
<artifactId>aspirin</artifactId>
|
||||
<version>1.9</version>
|
||||
<type>swc</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>flexlib</groupId>
|
||||
<artifactId>flexlib-bin</artifactId>
|
||||
<version>2.4</version>
|
||||
<type>swc</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>as3isolib</groupId>
|
||||
<artifactId>as3isolib-fp9</artifactId>
|
||||
<version>r298</version>
|
||||
<type>swc</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.threerings</groupId>
|
||||
<artifactId>nenyalib</artifactId>
|
||||
<version>1.5</version>
|
||||
<type>swc</type>
|
||||
</dependency>
|
||||
<!-- needed for the build, but not an exported dependency -->
|
||||
<dependency>
|
||||
<groupId>com.adobe.flex.framework</groupId>
|
||||
<artifactId>flex-framework</artifactId>
|
||||
<version>${flex.version}</version>
|
||||
<type>pom</type>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>flexmojos</id>
|
||||
<url>http://repository.sonatype.org/content/groups/flexgroup/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/as</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.flexmojos</groupId>
|
||||
<artifactId>flexmojos-maven-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<version>4.2-beta</version>
|
||||
<configuration>
|
||||
<omitTraceStatements>false</omitTraceStatements>
|
||||
<debug>true</debug>
|
||||
<incremental>false</incremental>
|
||||
<useNetwork>false</useNetwork>
|
||||
<verboseStacktraces>true</verboseStacktraces>
|
||||
<!-- we've never shown them in the Ant build, why start now? -->
|
||||
<showWarnings>false</showWarnings>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.adobe.flex</groupId>
|
||||
<artifactId>compiler</artifactId>
|
||||
<version>${flex.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.adobe.flex.compiler</groupId>
|
||||
<artifactId>asdoc</artifactId>
|
||||
<version>${flex.version}</version>
|
||||
<classifier>template</classifier>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,246 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.util.Byte;
|
||||
import com.threerings.util.Comparable;
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
/**
|
||||
* Instances of this class represent individual playing cards.
|
||||
*/
|
||||
public class Card
|
||||
implements DSet_Entry, Comparable, Hashable
|
||||
{
|
||||
/**
|
||||
* Creates a new card.
|
||||
*
|
||||
* @param number the number of the card
|
||||
* @param suit the suit of the card
|
||||
*/
|
||||
public function Card (number :int = 0, suit :int = 0)
|
||||
{
|
||||
_value = ((suit << 5) | number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the suit of the card: SPADES, HEARTS, DIAMONDS, or
|
||||
* CLUBS. If the card is the joker, the suit is undefined.
|
||||
*
|
||||
* @return the suit of the card
|
||||
*/
|
||||
public function getSuit () :int
|
||||
{
|
||||
return (_value >> 5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the card is a number card (2 to 10).
|
||||
*
|
||||
* @return true if the card is a number card, false otherwise
|
||||
*/
|
||||
public function isNumber () :Boolean
|
||||
{
|
||||
var number :int = getNumber();
|
||||
return number >= 2 && number <= 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the card is a face card (KING, QUEEN, or JACK).
|
||||
*
|
||||
* @return true if the card is a face card, false otherwise
|
||||
*/
|
||||
public function isFace () :Boolean
|
||||
{
|
||||
var number :int = getNumber();
|
||||
return number == CardCodes.KING || number == CardCodes.QUEEN ||
|
||||
number == CardCodes.JACK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the card is an ace.
|
||||
*
|
||||
* @return true if the card is an ace, false otherwise
|
||||
*/
|
||||
public function isAce () :Boolean
|
||||
{
|
||||
return getNumber() == CardCodes.ACE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the card is a joker.
|
||||
*
|
||||
* @return true if the card is a joker, false otherwise
|
||||
*/
|
||||
public function isJoker () :Boolean
|
||||
{
|
||||
var number :int = getNumber();
|
||||
return number == CardCodes.RED_JOKER || number == CardCodes.BLACK_JOKER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for this card.
|
||||
*
|
||||
* @return this card's hash code
|
||||
*/
|
||||
public function hashCode () :int
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this card to another. The card order is the same as the
|
||||
* initial deck ordering: two through ten, jack, queen, king, ace for
|
||||
* spades, hearts, clubs, and diamonds, then the red joker and the
|
||||
* black joker.
|
||||
*
|
||||
* @param other the other card to compare this to
|
||||
* @return -1, 0, or +1, depending on whether this card is less than,
|
||||
* equal to, or greater than the other card
|
||||
*/
|
||||
public function compareTo (other :Object) :int
|
||||
{
|
||||
var otherValue :int = (other as Card)._value;
|
||||
if (_value > otherValue) {
|
||||
return +1;
|
||||
} else if (_value < otherValue) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks this card for equality with another.
|
||||
*
|
||||
* @param other the other card to compare
|
||||
* @return true if the cards are equal, false otherwise
|
||||
*/
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
if (other is Card) {
|
||||
return _value == (other as Card)._value;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this card.
|
||||
*
|
||||
* @return a description of this card
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
var number :int = getNumber();
|
||||
|
||||
if (number == CardCodes.RED_JOKER) {
|
||||
return "RJ";
|
||||
|
||||
} else if (number == CardCodes.BLACK_JOKER) {
|
||||
return "BJ";
|
||||
|
||||
} else {
|
||||
return rankToString(number) + suitToString(getSuit());
|
||||
}
|
||||
}
|
||||
|
||||
// from interface DSet_Entry
|
||||
public function getKey () :Object
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of the card, either from 2 to 11 or
|
||||
* KING, QUEEN, JACK, ACE, RED_JOKER, or BLACK_JOKER.
|
||||
*
|
||||
* @return the value of the card
|
||||
*/
|
||||
public function getNumber () :int
|
||||
{
|
||||
return (_value & 0x1F);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not this card is valid. The no-arg public
|
||||
* constructor for deserialization creates an invalid card.
|
||||
*
|
||||
* @return true if this card is valid, false if not
|
||||
*/
|
||||
public function isValid () :Boolean
|
||||
{
|
||||
var number :int = getNumber(), suit :int = getSuit();
|
||||
return number == CardCodes.RED_JOKER ||
|
||||
number == CardCodes.BLACK_JOKER ||
|
||||
(number >= 2 && number <= CardCodes.ACE &&
|
||||
suit >= CardCodes.SPADES && suit <= CardCodes.DIAMONDS);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
_value = ins.readByte();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeByte(_value);
|
||||
}
|
||||
|
||||
protected function rankToString (rank :int) :String
|
||||
{
|
||||
if (rank >= 2 && rank <= 9) {
|
||||
return String(rank);
|
||||
}
|
||||
switch (rank) {
|
||||
case 10: return "T";
|
||||
case CardCodes.JACK: return "J";
|
||||
case CardCodes.QUEEN: return "Q";
|
||||
case CardCodes.KING: return "K";
|
||||
case CardCodes.ACE: return "A";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
protected function suitToString (suit :int) :String
|
||||
{
|
||||
switch (suit) {
|
||||
case CardCodes.SPADES: return "s";
|
||||
case CardCodes.HEARTS: return "h";
|
||||
case CardCodes.CLUBS: return "c";
|
||||
case CardCodes.DIAMONDS: return "d";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
/** The number of the card. */
|
||||
protected var _value :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.data {
|
||||
|
||||
/**
|
||||
* Constants relating to the card services.
|
||||
*/
|
||||
public class CardCodes
|
||||
{
|
||||
/** The suit of spades. */
|
||||
public static const SPADES :int = 0;
|
||||
|
||||
/** The suit of hearts. */
|
||||
public static const HEARTS :int = 1;
|
||||
|
||||
/** The suit of clubs. */
|
||||
public static const CLUBS :int = 2;
|
||||
|
||||
/** The suit of diamonds. */
|
||||
public static const DIAMONDS :int = 3;
|
||||
|
||||
/** The number of the jack. */
|
||||
public static const JACK :int = 11;
|
||||
|
||||
/** The number of the queen. */
|
||||
public static const QUEEN :int = 12;
|
||||
|
||||
/** The number of the king. */
|
||||
public static const KING :int = 13;
|
||||
|
||||
/** The number of the ace. */
|
||||
public static const ACE :int = 14;
|
||||
|
||||
/** The number of the red joker. */
|
||||
public static const RED_JOKER :int = 15;
|
||||
|
||||
/** The number of the black joker. */
|
||||
public static const BLACK_JOKER :int = 16;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.data {
|
||||
|
||||
import com.threerings.util.Arrays;
|
||||
import com.threerings.util.StreamableArrayList;
|
||||
|
||||
/**
|
||||
* Instances of this class represent decks of cards.
|
||||
*/
|
||||
public class Deck extends StreamableArrayList
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param includeJokers whether or not to include the two jokers
|
||||
* in the deck
|
||||
*/
|
||||
public function Deck (includeJokers :Boolean = false)
|
||||
{
|
||||
reset(includeJokers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deals a hand of cards from the deck.
|
||||
*
|
||||
* @param size the size of the hand to deal
|
||||
* @return the newly created and populated hand, or null
|
||||
* if there are not enough cards in the deck to deal the hand
|
||||
*/
|
||||
public function dealHand (size :int) :Hand
|
||||
{
|
||||
if (length < size) {
|
||||
return null;
|
||||
|
||||
} else {
|
||||
var hand :Hand = new Hand();
|
||||
var offset :int = length - size;
|
||||
for (var ii :int = 0; ii < size; ii++) {
|
||||
hand.add(removeAt(offset));
|
||||
}
|
||||
return hand;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hand of cards to the deck.
|
||||
*
|
||||
* @param hand the hand of cards to return
|
||||
*/
|
||||
public function returnHand (hand :Hand) :void
|
||||
{
|
||||
addAll(hand);
|
||||
hand.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the deck to its initial state: an unshuffled deck of
|
||||
* 52 or 54 cards, depending on whether the jokers are included.
|
||||
*
|
||||
* @param includeJokers whether or not to include the two jokers
|
||||
* in the deck
|
||||
*/
|
||||
public function reset (includeJokers :Boolean) :void
|
||||
{
|
||||
clear();
|
||||
|
||||
for (var ii :int = CardCodes.SPADES; ii <= CardCodes.DIAMONDS; ii++) {
|
||||
for (var jj :int = 2; jj <= CardCodes.ACE; jj++) {
|
||||
add(new Card(jj, ii));
|
||||
}
|
||||
}
|
||||
|
||||
if (includeJokers) {
|
||||
add(new Card(CardCodes.RED_JOKER, 3));
|
||||
add(new Card(CardCodes.BLACK_JOKER, 3));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffles the deck.
|
||||
*/
|
||||
public function shuffle () :void
|
||||
{
|
||||
Arrays.shuffle(_array);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.data {
|
||||
|
||||
import com.threerings.util.StreamableArrayList;
|
||||
|
||||
/**
|
||||
* Instances of this class represent hands of cards.
|
||||
*/
|
||||
public class Hand extends StreamableArrayList
|
||||
{
|
||||
public function Hand ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the members of a particular suit within this hand.
|
||||
*
|
||||
* @param suit the suit of interest
|
||||
* @return the number of cards in the specified suit
|
||||
*/
|
||||
public function getSuitMemberCount (suit :int) :int
|
||||
{
|
||||
var members :int = 0;
|
||||
for (var ii :int = 0; ii < length; ii++) {
|
||||
if ((get(ii) as Card).getSuit() == suit) {
|
||||
members++;
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of the cards in this hand.
|
||||
*/
|
||||
public function getCards () :Array
|
||||
{
|
||||
return toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the specified cards to this hand.
|
||||
*/
|
||||
public function addAllCards (cards :Array) :void
|
||||
{
|
||||
addAll(cards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this hand contains all of the specified cards.
|
||||
*/
|
||||
public function containsAllCards (cards :Array) :Boolean
|
||||
{
|
||||
for (var ii :int = 0; ii < cards.length; ii++) {
|
||||
if (!contains(cards[ii])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the specified cards from this hand.
|
||||
*/
|
||||
public function removeAllCards (cards :Array) :void
|
||||
{
|
||||
for (var ii :int = 0; ii < cards.length; ii++) {
|
||||
remove(cards[ii]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
/**
|
||||
* Pairs a player index with the card that the player played in the trick.
|
||||
*/
|
||||
public class PlayerCard
|
||||
implements Streamable
|
||||
{
|
||||
/** The index of the player. */
|
||||
public var pidx :int;
|
||||
|
||||
/** The card that the player played. */
|
||||
public var card :Card;
|
||||
|
||||
/**
|
||||
* Creates a new player card.
|
||||
*
|
||||
* @param pidx the index of the player
|
||||
* @param card the card played
|
||||
*/
|
||||
public function PlayerCard (pidx :int = 0, card :Card = null)
|
||||
{
|
||||
this.pidx = pidx;
|
||||
this.card = card;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
pidx = ins.readInt();
|
||||
card = Card(ins.readObject());
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(pidx);
|
||||
out.writeObject(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.trick.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java TrickCardGameService interface.
|
||||
*/
|
||||
public interface TrickCardGameService extends InvocationService
|
||||
{
|
||||
// from Java interface TrickCardGameService
|
||||
function playCard (arg1 :Card, arg2 :int) :void;
|
||||
|
||||
// from Java interface TrickCardGameService
|
||||
function requestRematch () :void;
|
||||
|
||||
// from Java interface TrickCardGameService
|
||||
function sendCardsToPlayer (arg1 :int, arg2 :TypedArray /* of class com.threerings.parlor.card.data.Card */) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.card.trick.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>TrickCardGameService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class TrickCardGameMarshaller extends InvocationMarshaller
|
||||
implements TrickCardGameService
|
||||
{
|
||||
/** The method id used to dispatch <code>playCard</code> requests. */
|
||||
public static const PLAY_CARD :int = 1;
|
||||
|
||||
// from interface TrickCardGameService
|
||||
public function playCard (arg1 :Card, arg2 :int) :void
|
||||
{
|
||||
sendRequest(PLAY_CARD, [
|
||||
arg1, Integer.valueOf(arg2)
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>requestRematch</code> requests. */
|
||||
public static const REQUEST_REMATCH :int = 2;
|
||||
|
||||
// from interface TrickCardGameService
|
||||
public function requestRematch () :void
|
||||
{
|
||||
sendRequest(REQUEST_REMATCH, [
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>sendCardsToPlayer</code> requests. */
|
||||
public static const SEND_CARDS_TO_PLAYER :int = 3;
|
||||
|
||||
// from interface TrickCardGameService
|
||||
public function sendCardsToPlayer (arg1 :int, arg2 :TypedArray /* of class com.threerings.parlor.card.data.Card */) :void
|
||||
{
|
||||
sendRequest(SEND_CARDS_TO_PLAYER, [
|
||||
Integer.valueOf(arg1), arg2
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import mx.controls.CheckBox;
|
||||
import mx.controls.ComboBox;
|
||||
import mx.controls.Label;
|
||||
|
||||
import com.threerings.parlor.data.RangeParameter;
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.data.ToggleParameter;
|
||||
import com.threerings.parlor.game.client.FlexGameConfigurator;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides a default implementation of a TableConfigurator for
|
||||
* a Swing interface.
|
||||
*/
|
||||
public class DefaultFlexTableConfigurator extends TableConfigurator
|
||||
{
|
||||
/**
|
||||
* Create a TableConfigurator that allows for the specified configuration parameters.
|
||||
*/
|
||||
public function DefaultFlexTableConfigurator (
|
||||
players :RangeParameter, watchable :ToggleParameter = null, prvate :ToggleParameter = null)
|
||||
{
|
||||
_playersParam = players;
|
||||
_watchableParam = watchable;
|
||||
_privateParam = prvate;
|
||||
|
||||
_config.minimumPlayerCount = players.minimum;
|
||||
|
||||
// create a slider for players, if applicable
|
||||
if (players.minimum != players.maximum) {
|
||||
_playersBox = new ComboBox();
|
||||
var values :Array = [];
|
||||
var startDex :int = 0;
|
||||
for (var ii :int = players.minimum; ii <= players.maximum; ii++) {
|
||||
if (ii == players.start) {
|
||||
startDex = ii;
|
||||
}
|
||||
values.push(ii);
|
||||
}
|
||||
_playersBox.dataProvider = values;
|
||||
_playersBox.selectedIndex = startDex;
|
||||
|
||||
} else {
|
||||
_config.desiredPlayerCount = players.start;
|
||||
}
|
||||
|
||||
if (watchable != null) {
|
||||
_watchableCheck = new CheckBox();
|
||||
_watchableCheck.selected = watchable.start;
|
||||
}
|
||||
|
||||
if (prvate != null) {
|
||||
_privateCheck = new CheckBox();
|
||||
_privateCheck.selected = prvate.start;
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override protected function createConfigInterface () :void
|
||||
{
|
||||
super.createConfigInterface();
|
||||
|
||||
var gconf :FlexGameConfigurator = (_gameConfigurator as FlexGameConfigurator);
|
||||
|
||||
if (_playersBox != null) {
|
||||
var playerLabel :Label = new Label();
|
||||
playerLabel.text = _playersParam.name;
|
||||
playerLabel.toolTip = _playersParam.tip;
|
||||
playerLabel.styleName = "lobbyLabel";
|
||||
gconf.addControl(playerLabel, _playersBox);
|
||||
}
|
||||
|
||||
if (_watchableCheck != null) {
|
||||
var watchableLabel :Label = new Label();
|
||||
watchableLabel.text = _watchableParam.name;
|
||||
watchableLabel.toolTip = _watchableParam.tip;
|
||||
watchableLabel.styleName = "lobbyLabel";
|
||||
gconf.addControl(watchableLabel, _watchableCheck);
|
||||
}
|
||||
|
||||
if (_privateCheck != null) {
|
||||
var privateLabel :Label = new Label();
|
||||
privateLabel.text = _privateParam.name;
|
||||
privateLabel.toolTip = _privateParam.tip;
|
||||
privateLabel.styleName = "lobbyLabel";
|
||||
gconf.addControl(privateLabel, _privateCheck);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function isEmpty () :Boolean
|
||||
{
|
||||
return (_playersBox == null) && (_watchableCheck == null) && (_privateCheck == null);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override protected function flushTableConfig () :void
|
||||
{
|
||||
super.flushTableConfig();
|
||||
|
||||
if (_playersBox != null) {
|
||||
_config.desiredPlayerCount = int(_playersBox.value);
|
||||
}
|
||||
|
||||
// TODO: it is wacky for the TableConfig.privateTable to mean two different things; it
|
||||
// should be extended to have separate privateTable and watchableTable options.
|
||||
if (_watchableCheck != null) {
|
||||
_config.privateTable = !_watchableCheck.selected;
|
||||
}
|
||||
if (_privateCheck != null) {
|
||||
_config.privateTable = _privateCheck.selected;
|
||||
}
|
||||
}
|
||||
|
||||
/** A component for configuring the number of players at the table. */
|
||||
protected var _playersBox :ComboBox;
|
||||
|
||||
/** A checkbox to allow the table creator to specify if the table is watchable */
|
||||
protected var _watchableCheck :CheckBox;
|
||||
|
||||
/** A checkbox to allow the table creator to specifiy if the table is private */
|
||||
protected var _privateCheck :CheckBox;
|
||||
|
||||
/** Configuration passed in by the caller */
|
||||
protected var _playersParam :RangeParameter;
|
||||
protected var _watchableParam :ToggleParameter;
|
||||
protected var _privateParam :ToggleParameter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
/**
|
||||
* Used to inform interested parties when the {@link ParlorDirector}
|
||||
* receives a game ready notification. The observers can ratify the
|
||||
* decision to head directly into the game or can take responsibility
|
||||
* themselves for doing so.
|
||||
*/
|
||||
public interface GameReadyObserver
|
||||
{
|
||||
/**
|
||||
* Called when a game ready notification is received.
|
||||
*
|
||||
* @param gameOid the place oid of the ready game.
|
||||
*
|
||||
* @return if the observer returns true from this method, the parlor
|
||||
* director assumes they will take care of entering the game room
|
||||
* after performing processing of their own. If all observers return
|
||||
* false, the director will enter the game room automatically.
|
||||
*/
|
||||
function receivedGameReady (gameOid :int) :Boolean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* The invitation class is used to track information related to
|
||||
* outstanding invitations generated by or targeted to this client.
|
||||
*/
|
||||
public class Invitation
|
||||
implements ParlorService_InviteListener
|
||||
{
|
||||
/** The unique id for this invitation (as assigned by the
|
||||
* server). This is -1 until we receive an acknowledgement from
|
||||
* the server that our invitation was delivered. */
|
||||
public var inviteId :int = -1;
|
||||
|
||||
/** The name of the other user involved in this invitation. */
|
||||
public var opponent :Name;
|
||||
|
||||
/** The configuration of the game to be created. */
|
||||
public var config :GameConfig;
|
||||
|
||||
/** Constructs a new invitation record. */
|
||||
public function Invitation (
|
||||
ctx :ParlorContext, pservice :ParlorService,
|
||||
opponent :Name, config :GameConfig,
|
||||
observer :InvitationResponseObserver)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_pservice = pservice;
|
||||
_observer = observer;
|
||||
this.opponent = opponent;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts this invitation.
|
||||
*/
|
||||
public function accept () :void
|
||||
{
|
||||
// generate the invocation service request
|
||||
_pservice.respond(inviteId, ParlorCodes.INVITATION_ACCEPTED, null, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refuses this invitation.
|
||||
*
|
||||
* @param message the message to deliver to the inviting user
|
||||
* explaining the reason for the refusal or null if no message is to
|
||||
* be provided.
|
||||
*/
|
||||
public function refuse (message :String) :void
|
||||
{
|
||||
// generate the invocation service request
|
||||
_pservice.respond(inviteId, ParlorCodes.INVITATION_REFUSED, message, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels this invitation.
|
||||
*/
|
||||
public function cancel () :void
|
||||
{
|
||||
// if the invitation has not yet been acknowleged by the
|
||||
// server, we make a note that it should be cancelled when we
|
||||
// do receive the acknowlegement
|
||||
if (inviteId == -1) {
|
||||
_cancelled = true;
|
||||
|
||||
} else {
|
||||
// otherwise, generate the invocation service request
|
||||
_pservice.cancel(inviteId, this);
|
||||
// and remove it from the pending table
|
||||
_ctx.getParlorDirector().clearInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Counters this invitation with an invitation with different game
|
||||
* configuration parameters.
|
||||
*
|
||||
* @param config the updated game configuration.
|
||||
* @param observer the entity that will be notified if this
|
||||
* counter-invitation is accepted, refused or countered.
|
||||
*/
|
||||
public function counter (
|
||||
config :GameConfig, observer :InvitationResponseObserver) :void
|
||||
{
|
||||
// update our observer (who will eventually be hearing back from
|
||||
// the other client about their counter-invitation)
|
||||
_observer = observer;
|
||||
|
||||
// generate the invocation service request
|
||||
_pservice.respond(inviteId, ParlorCodes.INVITATION_COUNTERED, config, this);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function inviteReceived (inviteId :int) :void
|
||||
{
|
||||
// fill in our invitation id
|
||||
this.inviteId = inviteId;
|
||||
|
||||
// if the invitation was cancelled before we heard back about
|
||||
// it, we need to send off a cancellation request now
|
||||
if (_cancelled) {
|
||||
_pservice.cancel(inviteId, this);
|
||||
} else {
|
||||
// otherwise, put it in the pending invites table
|
||||
_ctx.getParlorDirector().registerInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function requestFailed (reason :String) :void
|
||||
{
|
||||
// let the observer know what's up
|
||||
_observer.invitationRefused(this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the parlor director when we receive a response to an
|
||||
* invitation initiated by this client.
|
||||
*/
|
||||
internal function receivedResponse (code :int, arg :Object) :void
|
||||
{
|
||||
// make sure we have an observer to notify
|
||||
if (_observer == null) {
|
||||
Log.getLog(this).warning("No observer registered for invitation " +
|
||||
this + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// notify the observer
|
||||
try {
|
||||
switch (code) {
|
||||
case ParlorCodes.INVITATION_ACCEPTED:
|
||||
_observer.invitationAccepted(this);
|
||||
break;
|
||||
|
||||
case ParlorCodes.INVITATION_REFUSED:
|
||||
_observer.invitationRefused(this, (arg as String));
|
||||
break;
|
||||
|
||||
case ParlorCodes.INVITATION_COUNTERED:
|
||||
_observer.invitationCountered(this, (arg as GameConfig));
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (e :Error) {
|
||||
Log.getLog(this).warning("Invitation response observer choked on response",
|
||||
"code", code, "arg", arg, "invite", this, e);
|
||||
}
|
||||
|
||||
// unless the invitation was countered, we can remove it from the
|
||||
// pending table because it's resolved
|
||||
if (code != ParlorCodes.INVITATION_COUNTERED) {
|
||||
_ctx.getParlorDirector().clearInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a string representation of this invitation record. */
|
||||
public function toString () :String
|
||||
{
|
||||
return "[inviteId=" + inviteId + ", opponent=" + opponent +
|
||||
", config=" + config + ", observer=" + _observer +
|
||||
", cancelled=" + _cancelled + "]";
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected var _ctx :ParlorContext;
|
||||
|
||||
/** Provides access to parlor services. */
|
||||
protected var _pservice :ParlorService;
|
||||
|
||||
/** The entity to notify when we receive a response for this
|
||||
* invitation. */
|
||||
protected var _observer :InvitationResponseObserver;
|
||||
|
||||
/** A flag indicating that we were requested to cancel this
|
||||
* invitation before we even heard back with an acknowledgement
|
||||
* that it was received by the server. */
|
||||
protected var _cancelled :Boolean = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
/**
|
||||
* A client entity that wishes to handle invitations received by other
|
||||
* clients should implement this interface and register itself with the
|
||||
* parlor director. It will subsequently be notified of any incoming
|
||||
* invitations. It is also responsible for handling cancelled invitations.
|
||||
*/
|
||||
public interface InvitationHandler
|
||||
{
|
||||
/**
|
||||
* Called when an invitation is received from another player.
|
||||
*
|
||||
* @param invite the received invitation.
|
||||
*/
|
||||
function invitationReceived (invite :Invitation) :void;
|
||||
|
||||
/**
|
||||
* Called when an invitation is cancelled by the inviting player.
|
||||
*
|
||||
* @param invite the cancelled invitation.
|
||||
*/
|
||||
function invitationCancelled (invite :Invitation) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* A client entity that wishes to generate invitations for games must
|
||||
* implement this interface. An invitation can be accepted, refused or
|
||||
* countered. A countered invitation is one where the game configuration
|
||||
* is adjusted by the invited player and proposed back to the inviting
|
||||
* player.
|
||||
*/
|
||||
public interface InvitationResponseObserver
|
||||
{
|
||||
/**
|
||||
* Called if the invitation was accepted.
|
||||
*
|
||||
* @param invite the invitation for which we received a response.
|
||||
*/
|
||||
function invitationAccepted (invite :Invitation) :void;
|
||||
|
||||
/**
|
||||
* Called if the invitation was refused.
|
||||
*
|
||||
* @param invite the invitation for which we received a response.
|
||||
* @param message a message provided by the invited user explaining
|
||||
* the reason for their refusal, or the empty string if no message was
|
||||
* provided.
|
||||
*/
|
||||
function invitationRefused (invite :Invitation, message :String) :void;
|
||||
|
||||
/**
|
||||
* Called if the invitation was countered with an alternate game
|
||||
* configuration.
|
||||
*
|
||||
* @param invite the invitation for which we received a response.
|
||||
* @param config the game configuration proposed by the invited
|
||||
* player.
|
||||
*/
|
||||
function invitationCountered (invite :Invitation, config :GameConfig) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
|
||||
import com.threerings.parlor.client.ParlorReceiver;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link ParlorReceiver} instance.
|
||||
*/
|
||||
public class ParlorDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static const RECEIVER_CODE :String = "5ef9ee0d359c42a9024498ee9aad119a";
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#gameIsReady}
|
||||
* notifications. */
|
||||
public static const GAME_IS_READY :int = 1;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInvite}
|
||||
* notifications. */
|
||||
public static const RECEIVED_INVITE :int = 2;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteCancellation}
|
||||
* notifications. */
|
||||
public static const RECEIVED_INVITE_CANCELLATION :int = 3;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteResponse}
|
||||
* notifications. */
|
||||
public static const RECEIVED_INVITE_RESPONSE :int = 4;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public function ParlorDecoder (receiver :ParlorReceiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getReceiverCode () :String
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function dispatchNotification (
|
||||
methodId :int, args :Array) :void
|
||||
{
|
||||
var prec :ParlorReceiver = (receiver as ParlorReceiver);
|
||||
switch (methodId) {
|
||||
case GAME_IS_READY:
|
||||
prec.gameIsReady(args[0] as int);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE:
|
||||
prec.receivedInvite(
|
||||
(args[0] as int), (args[1] as Name),
|
||||
(args[2] as GameConfig)
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE_CANCELLATION:
|
||||
prec.receivedInviteCancellation(
|
||||
(args[0] as int)
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE_RESPONSE:
|
||||
prec.receivedInviteResponse(
|
||||
(args[0] as int), (args[1] as int), args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Arrays;
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
import com.threerings.util.Maps;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.data.ParlorMarshaller;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* The parlor director manages the client side of the game configuration and matchmaking processes.
|
||||
* It is also the entity that is listening for game start notifications which it then dispatches
|
||||
* the client entity that will actually create and display the user interface for the game that
|
||||
* started.
|
||||
*/
|
||||
public class ParlorDirector extends BasicDirector
|
||||
implements ParlorReceiver
|
||||
{
|
||||
// statically reference classes we require
|
||||
ParlorMarshaller;
|
||||
|
||||
/**
|
||||
* Constructs a parlor director and provides it with the parlor context that it can use to
|
||||
* access the client services that it needs to provide its own services. Only one parlor
|
||||
* director should be active in the client at one time and it should be made available via the
|
||||
* parlor context.
|
||||
*
|
||||
* @param ctx the parlor context in use by the client.
|
||||
*/
|
||||
public function ParlorDirector (ctx :ParlorContext)
|
||||
{
|
||||
super(ctx);
|
||||
_pctx = ctx;
|
||||
|
||||
// register ourselves with the invocation director as a parlor notification receiver
|
||||
_pctx.getClient().getInvocationDirector().registerReceiver(new ParlorDecoder(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the invitation handler, which is the entity that will be notified when we receive
|
||||
* incoming invitation notifications and when invitations have been cancelled.
|
||||
*
|
||||
* @param handler our new invitation handler.
|
||||
*/
|
||||
public function setInvitationHandler (handler :InvitationHandler) :void
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified observer to the list of entities that are notified when we receive a game
|
||||
* ready notification.
|
||||
*/
|
||||
public function addGameReadyObserver (observer :GameReadyObserver) :void
|
||||
{
|
||||
_grobs.push(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified observer from the list of entities that are notified when we receive a
|
||||
* game ready notification.
|
||||
*/
|
||||
public function removeGameReadyObserver (observer :GameReadyObserver) :void
|
||||
{
|
||||
Arrays.removeFirst(_grobs, observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the named user be invited to a game described by the supplied game config.
|
||||
*
|
||||
* @param invitee the user to invite.
|
||||
* @param config the configuration of the game to which the user is being invited.
|
||||
* @param observer the entity that will be notified if this invitation is accepted, refused or
|
||||
* countered.
|
||||
*
|
||||
* @return an invitation object that can be used to manage the outstanding invitation.
|
||||
*/
|
||||
public function invite (
|
||||
invitee :Name, config :GameConfig, observer :InvitationResponseObserver) :Invitation
|
||||
{
|
||||
// create the invitation record
|
||||
var invite :Invitation = new Invitation(_pctx, _pservice, invitee, config, observer);
|
||||
// submit the invitation request to the server
|
||||
_pservice.invite(invitee, config, invite);
|
||||
// and return the invitation to the caller
|
||||
return invite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified single player game be started.
|
||||
*
|
||||
* @param config the configuration of the single player game to be started.
|
||||
* @param listener a listener to be informed of failure if the game cannot be started.
|
||||
*/
|
||||
public function startSolitaire (
|
||||
config :GameConfig, listener :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
_pservice.startSolitaire(config, listener);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
_pservice = null;
|
||||
_pendingInvites.clear();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function gameIsReady (gameOid :int) :void
|
||||
{
|
||||
_log.info("Handling game ready", "goid", gameOid);
|
||||
|
||||
// see what our observers have to say about it
|
||||
var handled :Boolean = false;
|
||||
for (var ii :int = 0; ii < _grobs.length; ii++) {
|
||||
var grob :GameReadyObserver = (_grobs[ii] as GameReadyObserver);
|
||||
handled = grob.receivedGameReady(gameOid) || handled;
|
||||
}
|
||||
|
||||
// if none of the observers took matters into their own hands, then we'll head on over to
|
||||
// the game room ourselves
|
||||
if (!handled) {
|
||||
_pctx.getLocationDirector().moveTo(gameOid);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function receivedInvite (remoteId :int, inviter :Name, config :GameConfig) :void
|
||||
{
|
||||
// create an invitation record for this invitation
|
||||
var invite :Invitation = new Invitation(_pctx, _pservice, inviter, config, null);
|
||||
invite.inviteId = remoteId;
|
||||
|
||||
// put it in the pending invitations table
|
||||
_pendingInvites.put(remoteId, invite);
|
||||
|
||||
try {
|
||||
// notify the invitation handler of the incoming invitation
|
||||
_handler.invitationReceived(invite);
|
||||
|
||||
} catch (err :Error) {
|
||||
_log.warning("Invitation handler choked on invite notification", "invite", invite, err);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function receivedInviteResponse (remoteId :int, code :int, arg :Object) :void
|
||||
{
|
||||
// look up the invitation record for this invitation
|
||||
var invite :Invitation = (_pendingInvites.get(remoteId) as Invitation);
|
||||
if (invite == null) {
|
||||
_log.warning("Have no record of invitation for which we received a response?!",
|
||||
"remoteId", remoteId, "code", code, "arg", arg);
|
||||
} else {
|
||||
invite.receivedResponse(code, arg);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function receivedInviteCancellation (remoteId :int) :void
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new invitation in our pending invitations table. The invitation will call this
|
||||
* when it knows its invitation id.
|
||||
*/
|
||||
public function registerInvitation (invite :Invitation) :void
|
||||
{
|
||||
_pendingInvites.put(invite.inviteId, invite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by an invitation when it knows it is no longer and can be cleared from the pending
|
||||
* invitations table.
|
||||
*/
|
||||
public function clearInvitation (invite :Invitation) :void
|
||||
{
|
||||
_pendingInvites.remove(invite.inviteId);
|
||||
}
|
||||
|
||||
// from BasicDirector
|
||||
override protected function registerServices (client :Client) :void
|
||||
{
|
||||
client.addServiceGroup(ParlorCodes.PARLOR_GROUP);
|
||||
}
|
||||
|
||||
// from BasicDirector
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
// get a handle on our parlor services
|
||||
_pservice = (client.requireService(ParlorService) as ParlorService);
|
||||
super.fetchServices(client);
|
||||
}
|
||||
|
||||
/** An active parlor context. */
|
||||
protected var _pctx :ParlorContext;
|
||||
|
||||
/** Provides access to parlor server side services. */
|
||||
protected var _pservice :ParlorService;
|
||||
|
||||
/** The entity that has registered itself to handle incoming invitation notifications. */
|
||||
protected var _handler :InvitationHandler;
|
||||
|
||||
/** A table of acknowledged (but not yet accepted or refused) invitation requests, keyed on
|
||||
* invitation id. */
|
||||
protected var _pendingInvites :Map = Maps.newMapOf(int);
|
||||
|
||||
/** We notify the entities on this list when we get a game ready notification. */
|
||||
protected var _grobs :Array = new Array();
|
||||
|
||||
/** For great logging. */
|
||||
private var _log :Log = Log.getLog(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationReceiver;
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Defines, for the parlor services, a set of notifications delivered
|
||||
* asynchronously by the server to the client. These are handled by the
|
||||
* {@link ParlorDirector}.
|
||||
*/
|
||||
public interface ParlorReceiver extends InvocationReceiver
|
||||
{
|
||||
/**
|
||||
* Dispatched to the client when a game in which they are a
|
||||
* participant is ready for play. The client will then enter the game
|
||||
* room which will trigger the loading of the appropriate game UI code
|
||||
* and generally get things started.
|
||||
*
|
||||
* @param gameOid the object id of the game object.
|
||||
*/
|
||||
function gameIsReady (gameOid :int) :void;
|
||||
|
||||
/**
|
||||
* Called by the invocation services when another user has invited us
|
||||
* to play a game.
|
||||
*
|
||||
* @param remoteId the unique indentifier for this invitation (used
|
||||
* when countering or responding).
|
||||
* @param inviter the username of the inviting user.
|
||||
* @param config the configuration information for the game to which
|
||||
* we've been invited.
|
||||
*/
|
||||
function receivedInvite (
|
||||
remoteId :int, inviter :Name, config :GameConfig) :void;
|
||||
|
||||
/**
|
||||
* Called by the invocation services when another user has responded
|
||||
* to our invitation by either accepting, refusing or countering it.
|
||||
*
|
||||
* @param remoteId the indentifier for the invitation on question.
|
||||
* @param code the response code, either {@link
|
||||
* ParlorCodes#INVITATION_ACCEPTED} or {@link
|
||||
* ParlorCodes#INVITATION_REFUSED} or {@link
|
||||
* ParlorCodes#INVITATION_COUNTERED}.
|
||||
* @param arg in the case of a refused invitation, a string
|
||||
* containing a message provided by the invited user explaining the
|
||||
* reason for refusal (the empty string if no explanation was
|
||||
* provided). In the case of a countered invitation, a new game config
|
||||
* object with the modified game configuration.
|
||||
*/
|
||||
function receivedInviteResponse (
|
||||
remoteId :int, code :int, arg :Object) :void;
|
||||
|
||||
/**
|
||||
* Called by the invocation services when an outstanding invitation
|
||||
* has been cancelled by the inviting user.
|
||||
*
|
||||
* @param remoteId the indentifier of the cancelled invitation.
|
||||
*/
|
||||
function receivedInviteCancellation (remoteId :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java ParlorService interface.
|
||||
*/
|
||||
public interface ParlorService extends InvocationService
|
||||
{
|
||||
// from Java interface ParlorService
|
||||
function cancel (arg1 :int, arg2 :InvocationService_InvocationListener) :void;
|
||||
|
||||
// from Java interface ParlorService
|
||||
function invite (arg1 :Name, arg2 :GameConfig, arg3 :ParlorService_InviteListener) :void;
|
||||
|
||||
// from Java interface ParlorService
|
||||
function respond (arg1 :int, arg2 :int, arg3 :Object, arg4 :InvocationService_InvocationListener) :void;
|
||||
|
||||
// from Java interface ParlorService
|
||||
function startSolitaire (arg1 :GameConfig, arg2 :InvocationService_ConfirmListener) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java ParlorService_InviteListener interface.
|
||||
*/
|
||||
public interface ParlorService_InviteListener
|
||||
extends InvocationService_InvocationListener
|
||||
{
|
||||
// from Java ParlorService_InviteListener
|
||||
function inviteReceived (arg1 :int) :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
/**
|
||||
* Entites that wish to hear about when we sit down at a table or stand up
|
||||
* from a table can implement this interface and register themselves with
|
||||
* the {@link TableDirector}.
|
||||
*/
|
||||
public interface SeatednessObserver
|
||||
{
|
||||
/**
|
||||
* Called when this client sits down at or stands up from a table.
|
||||
*
|
||||
* @param isSeated true if the client is now seated at a table, false
|
||||
* if they are now no longer seated at a table.
|
||||
*/
|
||||
function seatednessDidChange (isSeated :Boolean) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* This should be implemented some user-interface element that allows
|
||||
* the user to configure whichever TableConfig options are relevant.
|
||||
*/
|
||||
public /*abstract*/ class TableConfigurator
|
||||
{
|
||||
/**
|
||||
* Create a TableConfigurator.
|
||||
*/
|
||||
public function TableConfigurator ()
|
||||
{
|
||||
_config = createTableConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally, you can set a pre-configured TableConfig
|
||||
* that will be used to initialize the display parameters (if possible).
|
||||
* This should be called prior to init().
|
||||
*/
|
||||
public function setTableConfig (config :TableConfig) :void
|
||||
{
|
||||
if (config != null) {
|
||||
_config = config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the TableConfigurator.
|
||||
*
|
||||
* At the time this is called, the GameConfigurator should have
|
||||
* already been initialized.
|
||||
*/
|
||||
public function init (
|
||||
ctx :ParlorContext, gameConfigurator :GameConfigurator) :void
|
||||
{
|
||||
_ctx = ctx;
|
||||
_gameConfigurator = gameConfigurator;
|
||||
createConfigInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the table config object that will be used.
|
||||
*/
|
||||
protected function createTableConfig () :TableConfig
|
||||
{
|
||||
return new TableConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the config interface.
|
||||
*/
|
||||
protected function createConfigInterface () :void
|
||||
{
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* If true, the TableConfigurator is empty, which doesn't mean that
|
||||
* it will not return a TableConfig object (for it must), but rather
|
||||
* that there are no user-editable options being presented in the
|
||||
* config interface.
|
||||
*/
|
||||
public /*abstract*/ function isEmpty () :Boolean
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the fully configured table config according to the currently
|
||||
* configured user interface elements.
|
||||
*/
|
||||
public function getTableConfig () :TableConfig
|
||||
{
|
||||
flushTableConfig();
|
||||
return _config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will want to override this method, flushing
|
||||
* values from the user interface to the table config object.
|
||||
*/
|
||||
protected function flushTableConfig () :void
|
||||
{
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected var _ctx :ParlorContext;
|
||||
|
||||
/** The config we're configurating. */
|
||||
protected var _config :TableConfig;
|
||||
|
||||
/** The game configurator, which we may wish to reference. */
|
||||
protected var _gameConfigurator :GameConfigurator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Arrays;
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Name;
|
||||
import com.threerings.util.ObserverList;
|
||||
import com.threerings.util.Util;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.InvocationService_ResultListener;
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.dobj.EntryAddedEvent;
|
||||
import com.threerings.presents.dobj.EntryRemovedEvent;
|
||||
import com.threerings.presents.dobj.EntryUpdatedEvent;
|
||||
import com.threerings.presents.dobj.SetListener;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
|
||||
import com.threerings.parlor.data.Table;
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.data.TableLobbyObject;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* As tables are created and managed within the scope of a place (a lobby), we want to fold the
|
||||
* table management functionality into the standard hierarchy of place controllers that deal with
|
||||
* place-related functionality on the client. Thus, instead of forcing places that expect to have
|
||||
* tables to extend a <code>TableLobbyController</code> or something similar, we instead provide
|
||||
* the table director which can be instantiated by the place controller (or specific table related
|
||||
* views) to handle the table matchmaking services.
|
||||
*
|
||||
* <p> Entites that do so, will need to implement the {@link TableObserver} interface so that the
|
||||
* table director can notify them when table related things happen. </p>
|
||||
*
|
||||
* <p> The table services expect that the place object being used as a lobby in which the table
|
||||
* matchmaking takes place implements the {@link TableLobbyObject} interface. </p>
|
||||
*/
|
||||
public class TableDirector extends BasicDirector
|
||||
implements SetListener, InvocationService_ResultListener
|
||||
{
|
||||
/**
|
||||
* Creates a new table director to manage tables with the specified observer which will receive
|
||||
* callbacks when interesting table related things happen.
|
||||
*
|
||||
* @param ctx the parlor context in use by the client.
|
||||
* @param tableField the field name of the distributed set that contains the tables we will be
|
||||
* managing.
|
||||
* @param bundle the message bundle to use when reporting errors.
|
||||
*/
|
||||
public function TableDirector (
|
||||
ctx :ParlorContext, tableField :String, errorBundle :String = null)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
// keep track of this stuff
|
||||
_pctx = ctx;
|
||||
_tableField = tableField;
|
||||
_errorBundle = errorBundle;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called by the entity that uses the table director when the using entity
|
||||
* prepares to enter and display a "place".
|
||||
*/
|
||||
public function setTableObject (tlobj :DObject) :void
|
||||
{
|
||||
// the distributed object should be a TableLobbyObject
|
||||
_tlobj = TableLobbyObject(tlobj);
|
||||
// listen for table set updates
|
||||
tlobj.addListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called by the entity that uses the table director when the using entity has
|
||||
* left and is done displaying the "place".
|
||||
*/
|
||||
public function clearTableObject () :void
|
||||
{
|
||||
// remove our listenership and clear out
|
||||
if (_tlobj != null) {
|
||||
(_tlobj as DObject).removeListener(this);
|
||||
_tlobj = null;
|
||||
_ourTable = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified observer be added to the list of observers that are notified
|
||||
* of table updates
|
||||
*/
|
||||
public function addTableObserver (observer :TableObserver) :void
|
||||
{
|
||||
_tableObservers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified observer be removed from to the list of observers that are
|
||||
* notified of table updates
|
||||
*/
|
||||
public function removeTableObserver (observer :TableObserver) :void
|
||||
{
|
||||
_tableObservers.remove(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified observer be added to the list of observers that are notified
|
||||
* when this client sits down at or stands up from a table.
|
||||
*/
|
||||
public function addSeatednessObserver (observer :SeatednessObserver) :void
|
||||
{
|
||||
_seatedObservers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified observer be removed from to the list of observers that are
|
||||
* notified when this client sits down at or stands up from a table.
|
||||
*/
|
||||
public function removeSeatednessObserver (observer :SeatednessObserver) :void
|
||||
{
|
||||
_seatedObservers.remove(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this client is currently seated at a table, false if they are not.
|
||||
*/
|
||||
public function isSeated () :Boolean
|
||||
{
|
||||
return (_ourTable != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the table this client is currently seated at, or null.
|
||||
*/
|
||||
public function getSeatedTable () :Table
|
||||
{
|
||||
return _ourTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, failure is handled by reporting feedback via the chat director. Clients that
|
||||
* require custom error handling can provide a function with the signature:
|
||||
* <pre>
|
||||
* function (cause :String) :void
|
||||
* </pre>
|
||||
*/
|
||||
public function setFailureHandler (handler :Function) :void
|
||||
{
|
||||
_failureHandler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to create a table with the specified game configuration. This user will
|
||||
* become the owner of this table and will be added to the first position in the table. The
|
||||
* response will be communicated via the {@link TableObserver} interface.
|
||||
*/
|
||||
public function createTable (tableConfig :TableConfig, config :GameConfig) :void
|
||||
{
|
||||
// if we're already in a table, refuse the request
|
||||
if (_ourTable != null) {
|
||||
log.warning("Ignoring request to create table as we're already in a table",
|
||||
"table", _ourTable);
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure we're currently in a place
|
||||
if (_tlobj == null) {
|
||||
log.warning("Requested to create a table but we're not currently in a place",
|
||||
"config", config);
|
||||
return;
|
||||
}
|
||||
|
||||
// go ahead and issue the create request
|
||||
_tlobj.getTableService().createTable(tableConfig, config, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to join the specified table at the specified position. The response will be
|
||||
* communicated via the {@link TableObserver} interface.
|
||||
*/
|
||||
public function joinTable (tableId :int, position :int) :void
|
||||
{
|
||||
// if we're already in a table, refuse the request
|
||||
if (_ourTable != null) {
|
||||
log.warning("Ignoring request to join table as we're already in a table",
|
||||
"table", _ourTable);
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure we're currently in a place
|
||||
if (_tlobj == null) {
|
||||
log.warning("Requested to join a table but we're not currently in a place",
|
||||
"tableId", tableId);
|
||||
return;
|
||||
}
|
||||
|
||||
// issue the join request
|
||||
log.info("Joining table", "tid", tableId, "pos", position);
|
||||
_tlobj.getTableService().joinTable(tableId, position, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to leave the specified table at which we are presumably seated. The response
|
||||
* will be communicated via the {@link TableObserver} interface.
|
||||
*/
|
||||
public function leaveTable (tableId :int) :void
|
||||
{
|
||||
// make sure we're currently in a place
|
||||
if (_tlobj == null) {
|
||||
log.warning("Requested to leave a table but we're not currently in a place",
|
||||
"tableId", tableId);
|
||||
return;
|
||||
}
|
||||
|
||||
// issue the leave request
|
||||
_tlobj.getTableService().leaveTable(tableId, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to have the specified table start now, even if all the seats have not yet
|
||||
* been filled.
|
||||
*/
|
||||
public function startTableNow (tableId :int) :void
|
||||
{
|
||||
if (_tlobj == null) {
|
||||
log.warning("Requested to start a table but we're not currently in a place",
|
||||
"tableId", tableId);
|
||||
return;
|
||||
}
|
||||
|
||||
_tlobj.getTableService().startTableNow(tableId, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to boot a player from a table.
|
||||
*/
|
||||
public function bootPlayer (tableId :int, target :Name) :void
|
||||
{
|
||||
if (_tlobj == null) {
|
||||
log.warning("Requesting to boot a player from a table we're not currently in",
|
||||
"tableId", tableId, "target", target);
|
||||
return;
|
||||
}
|
||||
|
||||
_tlobj.getTableService().bootPlayer(tableId, target, this);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
_tlobj = null;
|
||||
_ourTable = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function entryAdded (event :EntryAddedEvent) :void
|
||||
{
|
||||
if (event.getName() == _tableField) {
|
||||
var table :Table = (event.getEntry() as Table);
|
||||
// check to see if we just joined a table
|
||||
checkSeatedness(table);
|
||||
// now let the observers know what's up
|
||||
_tableObservers.apply(function (to :TableObserver) :void {
|
||||
to.tableAdded(table);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function entryUpdated (event :EntryUpdatedEvent) :void
|
||||
{
|
||||
if (event.getName() == _tableField) {
|
||||
var table :Table = (event.getEntry() as Table);
|
||||
// check to see if we just joined or left a table
|
||||
checkSeatedness(table);
|
||||
// now let the observers know what's up
|
||||
_tableObservers.apply(function (to :TableObserver) :void {
|
||||
to.tableUpdated(table);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function entryRemoved (event :EntryRemovedEvent) :void
|
||||
{
|
||||
if (event.getName() == _tableField) {
|
||||
var tableId :int = (event.getKey() as int);
|
||||
// check to see if our table just disappeared
|
||||
if (_ourTable != null && tableId == _ourTable.tableId) {
|
||||
_ourTable = null;
|
||||
notifySeatedness(false);
|
||||
}
|
||||
// now let the observer know what's up
|
||||
_tableObservers.apply(function (to :TableObserver) :void {
|
||||
to.tableRemoved(tableId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function requestProcessed (result :Object) :void
|
||||
{
|
||||
var tableId :int = int(result);
|
||||
if (_tlobj == null) {
|
||||
// we've left, it's none of our concern anymore
|
||||
log.info("Table created, but no lobby.", "tableId", tableId);
|
||||
return;
|
||||
}
|
||||
|
||||
var table :Table = (_tlobj.getTables().get(tableId) as Table);
|
||||
if (table == null) {
|
||||
log.warning("Table created, but where is it?", "tableId", tableId);
|
||||
return;
|
||||
}
|
||||
|
||||
// All this to check to see if we created a party game (and should now enter).
|
||||
if (table.gameOid != -1 && (table.players.length == 0)) {
|
||||
// let's boogie!
|
||||
_pctx.getParlorDirector().gameIsReady(table.gameOid);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function requestFailed (reason :String) :void
|
||||
{
|
||||
if (_failureHandler != null) {
|
||||
_failureHandler(reason);
|
||||
} else {
|
||||
_pctx.getChatDirector().displayFeedback(_errorBundle, reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if we're a member of this table and notes it as our table, if so.
|
||||
*/
|
||||
protected function checkSeatedness (table :Table) :void
|
||||
{
|
||||
var oldTable :Table = _ourTable;
|
||||
|
||||
// if this is the same table as our table, clear out our table reference and allow it to be
|
||||
// added back if we are still in the table
|
||||
if (table.equals(_ourTable)) {
|
||||
_ourTable = null;
|
||||
}
|
||||
|
||||
// look for our username in the players array
|
||||
var self :BodyObject = (_pctx.getClient().getClientObject() as BodyObject);
|
||||
if (Arrays.contains(table.players, self.getVisibleName())) {
|
||||
_ourTable = table;
|
||||
}
|
||||
|
||||
// if nothing changed, bail now
|
||||
if (Util.equals(oldTable, _ourTable)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise notify the observers
|
||||
notifySeatedness(_ourTable != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the seatedness observers of a seatedness change.
|
||||
*/
|
||||
protected function notifySeatedness (isSeated :Boolean) :void
|
||||
{
|
||||
_seatedObservers.apply(function (so :SeatednessObserver) :void {
|
||||
so.seatednessDidChange(isSeated);
|
||||
});
|
||||
}
|
||||
|
||||
/** A context by which we can access necessary client services. */
|
||||
protected var _pctx :ParlorContext;
|
||||
|
||||
/** The place object, cast as a TableLobbyObject. */
|
||||
protected var _tlobj :TableLobbyObject;
|
||||
|
||||
/** The field name of the distributed set that contains our tables. */
|
||||
protected var _tableField :String;
|
||||
|
||||
/** The message bundle to use when reporting errors. */
|
||||
protected var _errorBundle :String;
|
||||
|
||||
/** The table of which we are a member if any. */
|
||||
protected var _ourTable :Table;
|
||||
|
||||
/** An array of entities that want to hear about table updates. */
|
||||
protected var _tableObservers :ObserverList = new ObserverList();
|
||||
|
||||
/** An array of entities that want to hear about when we stand up or sit down. */
|
||||
protected var _seatedObservers :ObserverList = new ObserverList();
|
||||
|
||||
/** A custom failure handler, or null. */
|
||||
protected var _failureHandler :Function;
|
||||
|
||||
private static const log :Log = Log.getLog(TableDirector);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.parlor.data.Table;
|
||||
|
||||
/**
|
||||
* The {@link TableDirector} converts distributed object events into
|
||||
* higher level callbacks to implementers of this interface, which are
|
||||
* expected to render these events sensically in a user interface.
|
||||
*/
|
||||
public interface TableObserver
|
||||
{
|
||||
/**
|
||||
* Called when a new table is created.
|
||||
*/
|
||||
function tableAdded (table :Table) :void;
|
||||
|
||||
/**
|
||||
* Called when something has changed about a table (occupant list
|
||||
* updated, state changed from matchmaking to in-play, etc.).
|
||||
*/
|
||||
function tableUpdated (table :Table) :void;
|
||||
|
||||
/**
|
||||
* Called when a table goes away.
|
||||
*/
|
||||
function tableRemoved (tableId :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.client {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
import com.threerings.presents.client.InvocationService_ResultListener;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java TableService interface.
|
||||
*/
|
||||
public interface TableService extends InvocationService
|
||||
{
|
||||
// from Java interface TableService
|
||||
function bootPlayer (arg1 :int, arg2 :Name, arg3 :InvocationService_InvocationListener) :void;
|
||||
|
||||
// from Java interface TableService
|
||||
function createTable (arg1 :TableConfig, arg2 :GameConfig, arg3 :InvocationService_ResultListener) :void;
|
||||
|
||||
// from Java interface TableService
|
||||
function joinTable (arg1 :int, arg2 :int, arg3 :InvocationService_InvocationListener) :void;
|
||||
|
||||
// from Java interface TableService
|
||||
function leaveTable (arg1 :int, arg2 :InvocationService_InvocationListener) :void;
|
||||
|
||||
// from Java interface TableService
|
||||
function startTableNow (arg1 :int, arg2 :InvocationService_InvocationListener) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
/**
|
||||
* Models a parameter that allows the selection of one of a list of choices (specified as strings).
|
||||
*/
|
||||
public class ChoiceParameter extends Parameter
|
||||
{
|
||||
/** The set of choices available for this parameter. */
|
||||
public var choices :TypedArray;
|
||||
|
||||
/** The starting selection. */
|
||||
public var start :String;
|
||||
|
||||
public function ChoiceParameter ()
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getDefaultValue () :Object
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
choices = TypedArray(ins.readObject());
|
||||
start = (ins.readField(String) as String);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(choices);
|
||||
out.writeField(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
/**
|
||||
* Defines a configuration parameter for a game. Various derived classes exist that define
|
||||
* particular types of configuration parameters including choices, toggles, ranges, etc.
|
||||
*/
|
||||
public /*abstract*/ class Parameter
|
||||
implements Streamable
|
||||
{
|
||||
/** A string identifier that names this parameter. */
|
||||
public var ident :String;
|
||||
|
||||
/** A human readable name for this configuration parameter. */
|
||||
public var name :String;
|
||||
|
||||
/** A human readable tooltip to display when the mouse is hovered over this configuration
|
||||
* parameter. */
|
||||
public var tip :String;
|
||||
|
||||
public function Parameter ()
|
||||
{
|
||||
}
|
||||
|
||||
public function toString () :String
|
||||
{
|
||||
return ident;
|
||||
}
|
||||
|
||||
public function getDefaultValue () :Object
|
||||
{
|
||||
throw new Error("Abstract");
|
||||
}
|
||||
|
||||
/** Returns the translation key for this parameter's label. */
|
||||
public function getLabel () :String
|
||||
{
|
||||
return "m." + ident;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
ident = (ins.readField(String) as String);
|
||||
name = (ins.readField(String) as String);
|
||||
tip = (ins.readField(String) as String);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeField(ident);
|
||||
out.writeField(name);
|
||||
out.writeField(tip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
|
||||
/**
|
||||
* Contains codes used by the parlor invocation services.
|
||||
*/
|
||||
public class ParlorCodes extends InvocationCodes
|
||||
{
|
||||
/** Defines our invocation services group. */
|
||||
public static const PARLOR_GROUP :String = "parlor";
|
||||
|
||||
/** The response code for an accepted invitation. */
|
||||
public static const INVITATION_ACCEPTED :int = 0;
|
||||
|
||||
/** The response code for a refused invitation. */
|
||||
public static const INVITATION_REFUSED :int = 1;
|
||||
|
||||
/** The response code for a countered invitation. */
|
||||
public static const INVITATION_COUNTERED :int = 2;
|
||||
|
||||
/** An error code explaining that an invitation was rejected because the invited user was not
|
||||
* online at the time the invitation was received. */
|
||||
public static const INVITEE_NOT_ONLINE :String = "m.invitee_not_online";
|
||||
|
||||
/** An error code returned when a user requests to join a table that
|
||||
* doesn't exist. */
|
||||
public static const NO_SUCH_TABLE :String = "m.no_such_table";
|
||||
|
||||
/** An error code returned by the table services. */
|
||||
public static const INVALID_TABLE_POSITION :String = "m.invalid_table_position";
|
||||
|
||||
/** An error code returned by the table services. */
|
||||
public static const MUST_BE_CREATOR :String = "m.must_be_creator";
|
||||
|
||||
/** An error code returned by the table services. */
|
||||
public static const NO_SELF_BOOT :String = "m.no_self_boot";
|
||||
|
||||
/** An error code returned by the table services. */
|
||||
public static const TABLE_POSITION_OCCUPIED :String = "m.table_position_occupied";
|
||||
|
||||
/** An error code returned by the table services when a user requests to create or join a table
|
||||
* but they're already sitting at another table. */
|
||||
public static const ALREADY_AT_TABLE :String = "m.already_at_table";
|
||||
|
||||
/** An error code returned by the table services when a user requests to leave a table that
|
||||
* they were not sitting at in the first place. */
|
||||
public static const NOT_AT_TABLE :String = "m.not_at_table";
|
||||
|
||||
/** An error code returned by the table services for a request to join a table that the
|
||||
* requester been banned from. */
|
||||
public static const BANNED_FROM_TABLE :String = "m.banned_from_table";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ConfirmMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
|
||||
import com.threerings.parlor.client.ParlorService;
|
||||
import com.threerings.parlor.client.ParlorService_InviteListener;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>ParlorService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class ParlorMarshaller extends InvocationMarshaller
|
||||
implements ParlorService
|
||||
{
|
||||
/** The method id used to dispatch <code>cancel</code> requests. */
|
||||
public static const CANCEL :int = 1;
|
||||
|
||||
// from interface ParlorService
|
||||
public function cancel (arg1 :int, arg2 :InvocationService_InvocationListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(CANCEL, [
|
||||
Integer.valueOf(arg1), listener2
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>invite</code> requests. */
|
||||
public static const INVITE :int = 2;
|
||||
|
||||
// from interface ParlorService
|
||||
public function invite (arg1 :Name, arg2 :GameConfig, arg3 :ParlorService_InviteListener) :void
|
||||
{
|
||||
var listener3 :ParlorMarshaller_InviteMarshaller = new ParlorMarshaller_InviteMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(INVITE, [
|
||||
arg1, arg2, listener3
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>respond</code> requests. */
|
||||
public static const RESPOND :int = 3;
|
||||
|
||||
// from interface ParlorService
|
||||
public function respond (arg1 :int, arg2 :int, arg3 :Object, arg4 :InvocationService_InvocationListener) :void
|
||||
{
|
||||
var listener4 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
|
||||
listener4.listener = arg4;
|
||||
sendRequest(RESPOND, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), arg3, listener4
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>startSolitaire</code> requests. */
|
||||
public static const START_SOLITAIRE :int = 4;
|
||||
|
||||
// from interface ParlorService
|
||||
public function startSolitaire (arg1 :GameConfig, arg2 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(START_SOLITAIRE, [
|
||||
arg1, listener2
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
|
||||
import com.threerings.parlor.client.ParlorService_InviteListener;
|
||||
|
||||
/**
|
||||
* Marshalls instances of the ParlorService_InviteMarshaller interface.
|
||||
*/
|
||||
public class ParlorMarshaller_InviteMarshaller
|
||||
extends InvocationMarshaller_ListenerMarshaller
|
||||
{
|
||||
/** The method id used to dispatch <code>inviteReceived</code> responses. */
|
||||
public static const INVITE_RECEIVED :int = 1;
|
||||
|
||||
// from InvocationMarshaller_ListenerMarshaller
|
||||
override public function dispatchResponse (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case INVITE_RECEIVED:
|
||||
(listener as ParlorService_InviteListener).inviteReceived(
|
||||
(args[0] as int));
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Models a parameter that can contain an integer value in a specified range.
|
||||
*/
|
||||
public class RangeParameter extends Parameter
|
||||
{
|
||||
/** The minimum value of this parameter. */
|
||||
public var minimum :int;
|
||||
|
||||
/** The maximum value of this parameter. */
|
||||
public var maximum :int;
|
||||
|
||||
/** The starting value for this parameter. */
|
||||
public var start :int;
|
||||
|
||||
public function RangeParameter ()
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getDefaultValue () :Object
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
minimum = ins.readInt();
|
||||
maximum = ins.readInt();
|
||||
start = ins.readInt();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(minimum);
|
||||
out.writeInt(maximum);
|
||||
out.writeInt(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Arrays;
|
||||
import com.threerings.util.Hashable;
|
||||
import com.threerings.util.Joiner;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* This class represents a table that is being used to matchmake a game by the Parlor services.
|
||||
*/
|
||||
public class Table
|
||||
implements DSet_Entry, Hashable
|
||||
{
|
||||
/** Used to request any position at a table. */
|
||||
public static const ANY_POSITION :int = -1;
|
||||
|
||||
/** The unique identifier for this table. */
|
||||
public var tableId :int;
|
||||
|
||||
/** The object id of the lobby object with which this table is associated. */
|
||||
public var lobbyOid :int;
|
||||
|
||||
/** The oid of the game that was created from this table or -1 if the table is still in
|
||||
* matchmaking mode. */
|
||||
public var gameOid :int = -1;
|
||||
|
||||
/** An array of the usernames of the players of this table (some slots may not be filled), or
|
||||
* null if a party game. */
|
||||
public var players :TypedArray;
|
||||
|
||||
/** An array of the usernames of the non-player occupants of this game. For FFA party games
|
||||
* this is all of a room's occupants and they are in fact players. */
|
||||
public var watchers :TypedArray;
|
||||
|
||||
/** The body oids of the players of this table, or null if a party game. (This is not
|
||||
* propagated to remote instances.) */
|
||||
public var bodyOids :TypedArray;
|
||||
|
||||
/** The game config for the game that is being matchmade. */
|
||||
public var config :GameConfig;
|
||||
|
||||
/** The table configuration object. */
|
||||
public var tconfig :TableConfig;
|
||||
|
||||
/** Suitable for unserialization. */
|
||||
public function Table ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Once a table is ready to play (see {@link #mayBeStarted} and {@link #shouldBeStarted}), the
|
||||
* players array can be fetched using this method. It will return an array containing the
|
||||
* usernames of all of the players in the game, sized properly and with each player in the
|
||||
* appropriate position.
|
||||
*/
|
||||
public function getPlayers () :Array
|
||||
{
|
||||
var parray :Array = new Array();
|
||||
for (var ii :int = 0; ii < players.length; ii++) {
|
||||
if (players[ii] != null) {
|
||||
parray.push(players[ii]);
|
||||
}
|
||||
}
|
||||
return parray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of players currently occupying this table.
|
||||
*/
|
||||
public function getOccupiedCount () :int
|
||||
{
|
||||
var count :int = 0;
|
||||
if (players != null) {
|
||||
for (var ii :int = 0; ii < players.length; ii++) {
|
||||
if (players[ii] != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a team game, get the team member indices of the compressed players array returned by
|
||||
* getPlayers().
|
||||
*/
|
||||
public function getTeamMemberIndices () :TypedArray /* of Array of int */
|
||||
{
|
||||
var teams :Array = tconfig.teamMemberIndices;
|
||||
if (teams == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// compress the team indexes down
|
||||
var newTeams :TypedArray = new TypedArray("[[I");
|
||||
var players :Array = getPlayers();
|
||||
for (var ii :int = 0; ii < teams.length; ii++) {
|
||||
var subTeams :Array = (teams[ii] as Array);
|
||||
var newSubTeams :TypedArray = TypedArray.create(int);
|
||||
for (var jj :int = 0; jj < subTeams.length; jj++) {
|
||||
var occ :Name = (players[(subTeams[jj] as int)] as Name);
|
||||
if (occ != null) {
|
||||
newSubTeams.push(Arrays.indexOf(players, occ));
|
||||
}
|
||||
}
|
||||
newSubTeams.sort(null, Array.NUMERIC);
|
||||
newTeams[ii] = newSubTeams;
|
||||
}
|
||||
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table has a sufficient number of players that the game can be
|
||||
* started.
|
||||
*/
|
||||
public function mayBeStarted () :Boolean
|
||||
{
|
||||
switch (config.getMatchType()) {
|
||||
case GameConfig.SEATED_CONTINUOUS:
|
||||
case GameConfig.PARTY:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (tconfig.teamMemberIndices == null) {
|
||||
// for a normal game, just check to see if we're past the minimum
|
||||
return tconfig.minimumPlayerCount <= getOccupiedCount();
|
||||
|
||||
} else {
|
||||
// for a team game, make sure each team has the minimum players
|
||||
var teams :Array = tconfig.teamMemberIndices;
|
||||
for (var ii :int = 0; ii < teams.length; ii++) {
|
||||
var teamCount :int = 0;
|
||||
var members :Array = (teams[ii] as Array);
|
||||
for (var jj :int = 0; jj < members.length; jj++) {
|
||||
if (players[members[jj]] != null) {
|
||||
teamCount++;
|
||||
}
|
||||
}
|
||||
if (teamCount < tconfig.minimumPlayerCount) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if sufficient seats are occupied that the game should be automatically started.
|
||||
*/
|
||||
public function shouldBeStarted () :Boolean
|
||||
{
|
||||
switch (config.getMatchType()) {
|
||||
case GameConfig.SEATED_CONTINUOUS:
|
||||
case GameConfig.PARTY:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return (tconfig.desiredPlayerCount <= getOccupiedCount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table is in play, false if it is still being matchmade.
|
||||
*/
|
||||
public function inPlay () :Boolean
|
||||
{
|
||||
return gameOid != -1;
|
||||
}
|
||||
|
||||
// from Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return tableId;
|
||||
}
|
||||
|
||||
// from Hashable
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
return (other is Table) && (tableId == (other as Table).tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this table instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
var j :Joiner = Joiner.createFor(this);
|
||||
toStringJoiner(j);
|
||||
return j.toString();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getKey () :Object
|
||||
{
|
||||
return tableId;
|
||||
}
|
||||
|
||||
// from Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
tableId = ins.readInt();
|
||||
lobbyOid = ins.readInt();
|
||||
gameOid = ins.readInt();
|
||||
players = TypedArray(ins.readObject());
|
||||
watchers = TypedArray(ins.readObject());
|
||||
config = GameConfig(ins.readObject());
|
||||
tconfig = TableConfig(ins.readObject());
|
||||
}
|
||||
|
||||
// from Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(tableId);
|
||||
out.writeInt(lobbyOid);
|
||||
out.writeInt(gameOid);
|
||||
out.writeObject(players);
|
||||
out.writeObject(watchers);
|
||||
out.writeObject(config);
|
||||
out.writeObject(tconfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for toString, ripe for overrideability.
|
||||
*/
|
||||
protected function toStringJoiner (j :Joiner) :void
|
||||
{
|
||||
j.add("tableId", tableId, "lobbyOid", lobbyOid, "gameOid", gameOid,
|
||||
"players", players, "watchers", watchers, "config", config);
|
||||
}
|
||||
|
||||
/** A counter for assigning table ids. */
|
||||
protected static var _tableIdCounter :int = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
/**
|
||||
* Table configuration parameters for a game that is to be matchmade using the table services.
|
||||
*/
|
||||
public class TableConfig extends SimpleStreamableObject
|
||||
{
|
||||
/** The total number of players that are desired for the table. For team games, this should be
|
||||
* set to the total number of players overall, as teams may be unequal. */
|
||||
public var desiredPlayerCount :int;
|
||||
|
||||
/** The minimum number of players needed overall (or per-team if a team-based game) for the
|
||||
* game to start at the creator's discretion. */
|
||||
public var minimumPlayerCount :int;
|
||||
|
||||
/** If non-null, indicates that this is a team-based game and contains the team assignments for
|
||||
* each player. For example, a game with three players in two teams- players 0 and 2 versus
|
||||
* player 1- would have { {0, 2}, {1} }; */
|
||||
public var teamMemberIndices :TypedArray;
|
||||
|
||||
/** Whether the table is "private". */
|
||||
public var privateTable :Boolean;
|
||||
|
||||
public function TableConfig ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
// from Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
desiredPlayerCount = ins.readInt();
|
||||
minimumPlayerCount = ins.readInt();
|
||||
teamMemberIndices = TypedArray(ins.readObject());
|
||||
privateTable = ins.readBoolean();
|
||||
}
|
||||
|
||||
// from Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(desiredPlayerCount);
|
||||
out.writeInt(minimumPlayerCount);
|
||||
out.writeObject(teamMemberIndices);
|
||||
out.writeBoolean(privateTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
|
||||
/**
|
||||
* This interface must be implemented by the place object used by a lobby that wishes to make use
|
||||
* of the table services.
|
||||
*/
|
||||
public interface TableLobbyObject
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the distributed set instance that will be holding the tables.
|
||||
*/
|
||||
function getTables () :DSet;
|
||||
|
||||
/**
|
||||
* Adds the supplied table instance to the tables set (using the appropriate distributed object
|
||||
* mechanisms).
|
||||
*/
|
||||
function addToTables (table :Table) :void;
|
||||
|
||||
/**
|
||||
* Updates the value of the specified table instance in the tables distributed set (using the
|
||||
* appropriate distributed object mechanisms).
|
||||
*/
|
||||
function updateTables (table :Table) :void;
|
||||
|
||||
/**
|
||||
* Removes the table instance that matches the specified key from the tables set (using the
|
||||
* appropriate distributed object mechanisms).
|
||||
*/
|
||||
function removeFromTables (key :Object) :void;
|
||||
|
||||
/**
|
||||
* Returns a reference to the table service configured in this object.
|
||||
*/
|
||||
function getTableService () :TableMarshaller;
|
||||
|
||||
/**
|
||||
* Configures the table service that clients should use to communicate table requests back to
|
||||
* the table manager handling these tables.
|
||||
*/
|
||||
function setTableService (service :TableMarshaller) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
import com.threerings.presents.client.InvocationService_ResultListener;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ResultMarshaller;
|
||||
|
||||
import com.threerings.parlor.client.TableService;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>TableService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class TableMarshaller extends InvocationMarshaller
|
||||
implements TableService
|
||||
{
|
||||
/** The method id used to dispatch <code>bootPlayer</code> requests. */
|
||||
public static const BOOT_PLAYER :int = 1;
|
||||
|
||||
// from interface TableService
|
||||
public function bootPlayer (arg1 :int, arg2 :Name, arg3 :InvocationService_InvocationListener) :void
|
||||
{
|
||||
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(BOOT_PLAYER, [
|
||||
Integer.valueOf(arg1), arg2, listener3
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>createTable</code> requests. */
|
||||
public static const CREATE_TABLE :int = 2;
|
||||
|
||||
// from interface TableService
|
||||
public function createTable (arg1 :TableConfig, arg2 :GameConfig, arg3 :InvocationService_ResultListener) :void
|
||||
{
|
||||
var listener3 :InvocationMarshaller_ResultMarshaller = new InvocationMarshaller_ResultMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(CREATE_TABLE, [
|
||||
arg1, arg2, listener3
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>joinTable</code> requests. */
|
||||
public static const JOIN_TABLE :int = 3;
|
||||
|
||||
// from interface TableService
|
||||
public function joinTable (arg1 :int, arg2 :int, arg3 :InvocationService_InvocationListener) :void
|
||||
{
|
||||
var listener3 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(JOIN_TABLE, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), listener3
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>leaveTable</code> requests. */
|
||||
public static const LEAVE_TABLE :int = 4;
|
||||
|
||||
// from interface TableService
|
||||
public function leaveTable (arg1 :int, arg2 :InvocationService_InvocationListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(LEAVE_TABLE, [
|
||||
Integer.valueOf(arg1), listener2
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>startTableNow</code> requests. */
|
||||
public static const START_TABLE_NOW :int = 5;
|
||||
|
||||
// from interface TableService
|
||||
public function startTableNow (arg1 :int, arg2 :InvocationService_InvocationListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ListenerMarshaller = new InvocationMarshaller_ListenerMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(START_TABLE_NOW, [
|
||||
Integer.valueOf(arg1), listener2
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
/**
|
||||
* Models a parameter that allows the toggling of a single value.
|
||||
*/
|
||||
public class ToggleParameter extends Parameter
|
||||
{
|
||||
/** The starting state for this parameter. */
|
||||
public var start :Boolean;
|
||||
|
||||
public function ToggleParameter ()
|
||||
{
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getDefaultValue () :Object
|
||||
{
|
||||
return start;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
start = ins.readBoolean();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeBoolean(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.client {
|
||||
|
||||
import mx.containers.Grid;
|
||||
import mx.containers.GridItem;
|
||||
import mx.containers.GridRow;
|
||||
import mx.core.Container;
|
||||
import mx.core.UIComponent;
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
import com.threerings.flex.GridUtil;
|
||||
|
||||
/**
|
||||
* Provides the base from which interfaces can be built to configure games prior to starting them.
|
||||
* Derived classes would extend the base configurator adding interface elements and wiring them up
|
||||
* properly to allow the user to configure an instance of their game.
|
||||
*
|
||||
* <p> Clients that use the game configurator will want to instantiate one based on the class
|
||||
* returned from the {@link GameConfig} and then initialize it with a call to {@link #init}. </p>
|
||||
*/
|
||||
public /*abstract*/ class FlexGameConfigurator extends GameConfigurator
|
||||
{
|
||||
/**
|
||||
* Configures the number of columns to use when laying out our controls. This must be called
|
||||
* before any calls to {@link #addControl}.
|
||||
*/
|
||||
public function setColumns (columns :int) :void
|
||||
{
|
||||
_columns = columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Container that contains the UI elements for this configurator.
|
||||
*/
|
||||
public function getContainer () :Container
|
||||
{
|
||||
return _grid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a control to the interface. This should be the standard way that configurator controls
|
||||
* are added, but note also that external entities may add their own controls that are related
|
||||
* to the game, but do not directly alter the game config, so that all the controls are added
|
||||
* in a uniform manner and are well aligned.
|
||||
*/
|
||||
public function addControl (label :UIComponent, control :UIComponent,
|
||||
verticalAlign :String = "middle") :void
|
||||
{
|
||||
if (_gridRow == null) {
|
||||
_gridRow = new GridRow();
|
||||
_grid.addChild(_gridRow);
|
||||
}
|
||||
|
||||
var item :GridItem = GridUtil.addToRow(_gridRow, label);
|
||||
item.setStyle("verticalAlign", verticalAlign);
|
||||
if (_gridRow.numChildren > 1) {
|
||||
item.setStyle("paddingLeft", 15);
|
||||
}
|
||||
item = GridUtil.addToRow(_gridRow, control);
|
||||
item.setStyle("verticalAlign", verticalAlign);
|
||||
|
||||
if (_gridRow.numChildren == _columns * 2) {
|
||||
_gridRow = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The grid on which the config options are placed. */
|
||||
protected var _grid :Grid = new Grid();
|
||||
|
||||
/** The current row to which we're adding controls. */
|
||||
protected var _gridRow :GridRow;
|
||||
|
||||
/** The number of columns in which to lay out our configuration. */
|
||||
protected var _columns :int = 2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.client {
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* Provides the base from which interfaces can be built to configure games prior to starting
|
||||
* them. Derived classes would extend the base configurator adding interface elements and wiring
|
||||
* them up properly to allow the user to configure an instance of their game.
|
||||
*
|
||||
* <p> Clients that use the game configurator will want to instantiate one based on the class
|
||||
* returned from the {@link GameConfig} and then initialize it with a call to {@link #init}. </p>
|
||||
*/
|
||||
public /*abstract*/ class GameConfigurator
|
||||
{
|
||||
/**
|
||||
* Initializes this game configurator, creates its user interface elements and prepares it for
|
||||
* display.
|
||||
*/
|
||||
public function init (ctx :ParlorContext) :void
|
||||
{
|
||||
// save this for later
|
||||
_ctx = ctx;
|
||||
|
||||
// create our interface elements
|
||||
createConfigInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation creates nothing.
|
||||
*/
|
||||
protected function createConfigInterface () :void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides this configurator with its configuration. It should set up all of its user
|
||||
* interface elements to reflect the configuration.
|
||||
*/
|
||||
public function setGameConfig (config :GameConfig) :void
|
||||
{
|
||||
_config = config;
|
||||
// set up the user interface
|
||||
gotGameConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will likely want to override this method and configure their user interface
|
||||
* elements accordingly.
|
||||
*/
|
||||
protected function gotGameConfig () :void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a configured game configuration.
|
||||
*/
|
||||
public function getGameConfig () :GameConfig
|
||||
{
|
||||
// flush our changes to the config object
|
||||
flushGameConfig();
|
||||
return _config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will want to override this method, flushing values from the user interface
|
||||
* to the game config object so that it is properly configured prior to being returned to the
|
||||
* {@link #getGameConfig} caller.
|
||||
*/
|
||||
protected function flushGameConfig () :void
|
||||
{
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected var _ctx :ParlorContext;
|
||||
|
||||
/** Our game configuration. */
|
||||
protected var _config :GameConfig;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.client {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.parlor.game.data.GameCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.game.data.GameObject;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
/**
|
||||
* The game controller manages the flow and control of a game on the
|
||||
* client side. This class serves as the root of a hierarchy of controller
|
||||
* classes that aim to provide functionality shared between various
|
||||
* similar games. The base controller provides functionality for starting
|
||||
* and ending the game and for calculating ratings adjustements when a
|
||||
* game ends normally. It also handles the basic house keeping like
|
||||
* subscription to the game object and dispatch of commands and
|
||||
* distributed object events.
|
||||
*/
|
||||
public /*abstract*/ class GameController extends PlaceController
|
||||
implements AttributeChangeListener
|
||||
{
|
||||
/**
|
||||
* Initializes this game controller with the game configuration that
|
||||
* was established during the match making process. Derived classes
|
||||
* may want to override this method to initialize themselves with
|
||||
* game-specific configuration parameters but they should be sure to
|
||||
* call <code>super.init</code> in such cases.
|
||||
*
|
||||
* @param ctx the client context.
|
||||
* @param config the configuration of the game we are intended to
|
||||
* control.
|
||||
*/
|
||||
override public function init (ctx :CrowdContext, config :PlaceConfig) :void
|
||||
{
|
||||
// cast our references before we call super.init() so that when
|
||||
// super.init() calls createPlaceView(), we have our casted
|
||||
// references already in place
|
||||
_pctx = (ctx as ParlorContext);
|
||||
_gconfig = (config as GameConfig);
|
||||
|
||||
super.init(ctx, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds this controller as a listener to the game object (thus derived classes need not do so)
|
||||
* and lets the game manager know that we are now ready to go.
|
||||
*/
|
||||
override public function willEnterPlace (plobj :PlaceObject) :void
|
||||
{
|
||||
super.willEnterPlace(plobj);
|
||||
|
||||
// obtain a casted reference
|
||||
_gobj = (plobj as GameObject);
|
||||
|
||||
// if this place object is not our current location we'll need to add it as an auxiliary
|
||||
// chat source
|
||||
var bobj :BodyObject = (_ctx.getClient().getClientObject() as BodyObject);
|
||||
if (bobj.getPlaceOid() != plobj.getOid()) {
|
||||
_ctx.getChatDirector().addAuxiliarySource(_gobj, GameCodes.GAME_CHAT_TYPE);
|
||||
}
|
||||
|
||||
// and add ourselves as a listener
|
||||
_gobj.addListener(this);
|
||||
|
||||
// potentially let the game manager know that we're ready to roll
|
||||
if (shouldAutoPlayerReady(bobj)) {
|
||||
// we don't want to claim to be finished until any derived classes that overrode this
|
||||
// method have executed, so we'll queue up a runnable here that will let the game
|
||||
// manager know that we're ready on the next pass through the distributed event loop
|
||||
_ctx.getClient().callLater(playerReady);
|
||||
}
|
||||
|
||||
log.info("Entered game " + _gobj.which() + ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes our listener registration from the game object and cleans
|
||||
* house.
|
||||
*/
|
||||
override public function didLeavePlace (plobj :PlaceObject) :void
|
||||
{
|
||||
super.didLeavePlace(plobj);
|
||||
|
||||
_ctx.getChatDirector().removeAuxiliarySource(_gobj);
|
||||
|
||||
// unlisten to the game object
|
||||
_gobj.removeListener(this);
|
||||
_gobj = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the game is over.
|
||||
*/
|
||||
public function isGameOver () :Boolean
|
||||
{
|
||||
var gameOver :Boolean = (_gobj == null) ||
|
||||
(_gobj.state != GameObject.IN_PLAY);
|
||||
return (_gameOver || gameOver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client game over override. This is used in situations
|
||||
* where we determine that the game is over before the server has
|
||||
* informed us of such.
|
||||
*/
|
||||
public function setGameOver (gameOver :Boolean) :void
|
||||
{
|
||||
_gameOver = gameOver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link #gameWillReset}, ends the current game (locally, it
|
||||
* does not tell the server to end the game), and waits to receive a
|
||||
* reset notification (which is simply an event setting the game state
|
||||
* to <code>IN_PLAY</code> even though it's already set to
|
||||
* <code>IN_PLAY</code>) from the server which will start up a new
|
||||
* game. Derived classes should override {@link #gameWillReset} to
|
||||
* perform any game-specific animations.
|
||||
*/
|
||||
public function resetGame () :void
|
||||
{
|
||||
// let derived classes do their thing
|
||||
gameWillReset();
|
||||
|
||||
// end the game until we receive a new board
|
||||
setGameOver(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique identifier for the current gameplay session.
|
||||
*/
|
||||
public function getSessionId () :int
|
||||
{
|
||||
return (_gobj == null) ? -1 : _gobj.sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles basic game controller action events. Derived classes should
|
||||
* be sure to call <code>super.handleAction</code> for events they
|
||||
* don't specifically handle.
|
||||
*/
|
||||
override public function handleAction (cmd :String, arg :Object) :Boolean
|
||||
{
|
||||
return super.handleAction(cmd, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* A way for controllers to display a game-related system message.
|
||||
*/
|
||||
public function systemMessage (bundle :String, msg :String) :void
|
||||
{
|
||||
_ctx.getChatDirector().displayInfo(
|
||||
bundle, msg, GameCodes.GAME_CHAT_TYPE);
|
||||
}
|
||||
|
||||
// from interface AttributeChangeListener
|
||||
public function attributeChanged (event :AttributeChangedEvent) :void
|
||||
{
|
||||
// deal with game state changes
|
||||
var name :String = event.getName();
|
||||
if (GameObject.STATE == name) {
|
||||
var newState :int = int(event.getValue());
|
||||
if (!stateDidChange(newState)) {
|
||||
log.warning("Game transitioned to unknown state " +
|
||||
"[gobj=" + _gobj + ", state=" + newState + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes can override this method if they add additional game states and should
|
||||
* handle transitions to those states, returning true to indicate they were handled and calling
|
||||
* super for the normal game states.
|
||||
*/
|
||||
protected function stateDidChange (state :int) :Boolean
|
||||
{
|
||||
switch (state) {
|
||||
case GameObject.PRE_GAME:
|
||||
return true;
|
||||
case GameObject.IN_PLAY:
|
||||
gameDidStart();
|
||||
return true;
|
||||
case GameObject.GAME_OVER:
|
||||
gameDidEnd();
|
||||
return true;
|
||||
case GameObject.CANCELLED:
|
||||
gameWasCancelled();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if we should automatically call playerReady() in willEnterPlace().
|
||||
*/
|
||||
protected function shouldAutoPlayerReady (bobj :BodyObject) :Boolean
|
||||
{
|
||||
return (_gobj.getPlayerIndex(bobj.getVisibleName()) != -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after we've entered the game and everything has initialized
|
||||
* to notify the server that we, as a player, are ready to play.
|
||||
*/
|
||||
protected function playerReady () :void
|
||||
{
|
||||
log.info("Reporting ready " + _gobj.which() + ".");
|
||||
_gobj.manager.invoke("playerReady");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game transitions to the <code>IN_PLAY</code>
|
||||
* state. This happens when all of the players have arrived and the
|
||||
* server starts the game.
|
||||
*/
|
||||
protected function gameDidStart () :void
|
||||
{
|
||||
if (_gobj == null) {
|
||||
log.info("Received gameDidStart() after leaving game room.");
|
||||
return;
|
||||
}
|
||||
|
||||
// clear out our game over flag
|
||||
setGameOver(false);
|
||||
|
||||
// let our delegates do their business
|
||||
applyToDelegates(function (del :GameControllerDelegate) :void {
|
||||
del.gameDidStart();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game transitions to the <code>GAME_OVER</code>
|
||||
* state. This happens when the game reaches some end condition by
|
||||
* normal means (is not cancelled or aborted).
|
||||
*/
|
||||
protected function gameDidEnd () :void
|
||||
{
|
||||
// let our delegates do their business
|
||||
applyToDelegates(function (del :GameControllerDelegate) :void {
|
||||
del.gameDidEnd();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game was cancelled for some reason.
|
||||
*/
|
||||
protected function gameWasCancelled () :void
|
||||
{
|
||||
// let our delegates do their business
|
||||
applyToDelegates(function (del :GameControllerDelegate) :void {
|
||||
del.gameWasCancelled();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to give derived classes a chance to display animations, send
|
||||
* a final packet, or do any other business they care to do when the
|
||||
* game is about to reset.
|
||||
*/
|
||||
protected function gameWillReset () :void
|
||||
{
|
||||
// let our delegates do their business
|
||||
applyToDelegates(function (del :GameControllerDelegate) :void {
|
||||
del.gameWillReset();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to determine the type of game.
|
||||
*/
|
||||
protected function getMatchType () :int
|
||||
{
|
||||
return _gconfig.getMatchType();
|
||||
}
|
||||
|
||||
/** A reference to the active parlor context. */
|
||||
protected var _pctx :ParlorContext;
|
||||
|
||||
/** Our game configuration information. */
|
||||
protected var _gconfig :GameConfig;
|
||||
|
||||
/** A reference to the game object for the game that we're
|
||||
* controlling. */
|
||||
protected var _gobj :GameObject;
|
||||
|
||||
/** A local flag overriding the game over state for situations where
|
||||
* the client knows the game is over before the server has
|
||||
* transitioned the game object accordingly. */
|
||||
protected var _gameOver :Boolean;
|
||||
|
||||
private static const log :Log = Log.getLog(GameController);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.client {
|
||||
|
||||
import com.threerings.crowd.client.PlaceControllerDelegate;
|
||||
|
||||
/**
|
||||
* Extends the {@link PlaceControllerDelegate} mechanism with game
|
||||
* controller specific methods.
|
||||
*/
|
||||
public class GameControllerDelegate extends PlaceControllerDelegate
|
||||
{
|
||||
/**
|
||||
* Provides the delegate with a reference to the game controller for
|
||||
* which it is delegating.
|
||||
*/
|
||||
public function GameControllerDelegate (ctrl :GameController)
|
||||
{
|
||||
super(ctrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game transitions to the <code>IN_PLAY</code>
|
||||
* state. This happens when all of the players have arrived and the
|
||||
* server starts the game.
|
||||
*/
|
||||
public function gameDidStart () :void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game transitions to the <code>GAME_OVER</code>
|
||||
* state. This happens when the game reaches some end condition by
|
||||
* normal means (is not cancelled or aborted).
|
||||
*/
|
||||
public function gameDidEnd () :void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game was cancelled for some reason.
|
||||
*/
|
||||
public function gameWasCancelled () :void
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to give derived classes a chance to display animations, send
|
||||
* a final packet, or do any other business they care to do when the
|
||||
* game is about to reset.
|
||||
*/
|
||||
public function gameWillReset () :void
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
/**
|
||||
* Represents attributes of an AI player.
|
||||
*/
|
||||
public class GameAI extends SimpleStreamableObject
|
||||
{
|
||||
/** The "personality" of the AI, which can be interpreted by
|
||||
* each puzzle. */
|
||||
public var personality :int;
|
||||
|
||||
/** The skill level of the AI. */
|
||||
public var skill :int;
|
||||
|
||||
/**
|
||||
* Constructs an AI with the specified (game-interpreted) skill and
|
||||
* personality.
|
||||
*/
|
||||
public function GameAI (personality :int = 0, skill :int = 0)
|
||||
{
|
||||
this.personality = personality;
|
||||
this.skill = skill;
|
||||
}
|
||||
|
||||
// from Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
personality = ins.readInt();
|
||||
skill = ins.readInt();
|
||||
}
|
||||
|
||||
// from Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(personality);
|
||||
out.writeInt(skill);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.data {
|
||||
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
|
||||
/**
|
||||
* Constants relating to the game services.
|
||||
*/
|
||||
public class GameCodes extends InvocationCodes
|
||||
{
|
||||
/** The message bundle identifier for general game messages. */
|
||||
public static const GAME_MESSAGE_BUNDLE :String = "game.general";
|
||||
|
||||
/** The name of the message event to a placeObject that a player
|
||||
* was knocked out of a puzzle. */
|
||||
public static const PLAYER_KNOCKED_OUT :String = "playerKnocked";
|
||||
|
||||
/** The name of the message event to a placeObject that reports
|
||||
* the winners and losers of a game. */
|
||||
public static const WINNERS_AND_LOSERS :String = "winnersAndLosers";
|
||||
|
||||
/** A chat type for chatting on the game object. */
|
||||
public static const GAME_CHAT_TYPE :String = "gameChat";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Hashable;
|
||||
import com.threerings.util.Name;
|
||||
import com.threerings.util.StringUtil;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.parlor.client.TableConfigurator;
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
|
||||
/**
|
||||
* The game config class encapsulates the configuration information for a particular type of
|
||||
* game. The hierarchy of game config objects mimics the hierarchy of game managers and
|
||||
* controllers. Both the game manager and game controller are provided with the game config object
|
||||
* when the game is created.
|
||||
*
|
||||
* <p> The game config object is also the mechanism used to instantiate the appropriate game
|
||||
* manager and controller. Every game must have an associated game config derived class that
|
||||
* overrides {@link #createController} and {@link #getManagerClassName}, returning the appropriate
|
||||
* game controller and manager class for that game. Thus the entire chain of events that causes a
|
||||
* particular game to be created is the construction of the appropriate game config instance which
|
||||
* is provided to the server as part of an invitation or via some other matchmaking mechanism. </p>
|
||||
*/
|
||||
public /*abstract*/ class GameConfig extends PlaceConfig
|
||||
implements Cloneable, Hashable
|
||||
{
|
||||
/** Game type constant: a game that is started with a list of players, and those are the only
|
||||
* players that may play. */
|
||||
public static const SEATED_GAME :int = 0;
|
||||
|
||||
/** Game type constant: a game that starts immediately, but only has a certain number of player
|
||||
* slots. Users enter the game room, and then choose where to sit. */
|
||||
public static const SEATED_CONTINUOUS :int = 1;
|
||||
|
||||
/** Game type constant: a game that starts immediately, and every user that enters is a
|
||||
* player. */
|
||||
public static const PARTY :int = 2;
|
||||
|
||||
/** The usernames of the players involved in this game, or an empty array if such information
|
||||
* is not needed by this particular game. */
|
||||
public var players :TypedArray = TypedArray.create(Name);
|
||||
|
||||
/** Indicates whether or not this game is rated. */
|
||||
public var rated :Boolean = true;
|
||||
|
||||
/** Configurations for AIs to be used in this game. Slots with real players should be null and
|
||||
* slots with AIs should contain configuration for those AIs. A null array indicates no use of
|
||||
* AIs at all. */
|
||||
public var ais :TypedArray = TypedArray.create(GameAI);
|
||||
|
||||
public function GameConfig ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a numeric identifier for this game class. This may be used to track persisent
|
||||
* information on a per-game basis.
|
||||
*/
|
||||
public function getGameId () :int
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
public function getGameIdent () :String
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of game.
|
||||
*/
|
||||
public function getMatchType () :int
|
||||
{
|
||||
return SEATED_GAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a configurator that can be used to create a user interface for configuring this
|
||||
* instance prior to starting the game. If no configuration is necessary, this method should
|
||||
* return null.
|
||||
*/
|
||||
public /*abstract*/ function createConfigurator () :GameConfigurator
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a table configurator for initializing 'table' properties of the game. The default
|
||||
* implementation returns null.
|
||||
*/
|
||||
public function createTableConfigurator () :TableConfigurator
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hashcode for this game config object that supports our {@link #equals}
|
||||
* implementation. Objects that are equal should have the same hashcode.
|
||||
*/
|
||||
public function hashCode () :int
|
||||
{
|
||||
// look ma, it's so sophisticated!
|
||||
return StringUtil.hashCode(ClassUtil.getClassName(this)) + (rated ? 1 : 0);
|
||||
}
|
||||
|
||||
// from Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
var copy :GameConfig = (ClassUtil.newInstance(this) as GameConfig);
|
||||
copy.players = this.players;
|
||||
copy.rated = this.rated;
|
||||
copy.ais = this.ais;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this game config object is equal to the supplied object (meaning it is also
|
||||
* a game config object and its configuration settings are the same as ours).
|
||||
*/
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
// make sure they're of the same class
|
||||
if (ClassUtil.isSameClass(other, this)) {
|
||||
var that :GameConfig = GameConfig(other);
|
||||
return this.getGameId() == that.getGameId() && this.rated == that.rated;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Array of strings that describe the configuration of this game. Default
|
||||
* implementation returns an empty array.
|
||||
*/
|
||||
public function getDescription () :Array
|
||||
{
|
||||
return new Array(); // nothing by default
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
players = TypedArray(ins.readObject());
|
||||
rated = ins.readBoolean();
|
||||
ais = TypedArray(ins.readObject());
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(players);
|
||||
out.writeBoolean(rated);
|
||||
out.writeObject(ais);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,435 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Arrays;
|
||||
import com.threerings.util.Integer;
|
||||
import com.threerings.util.Joiner;
|
||||
import com.threerings.util.Name;
|
||||
import com.threerings.util.langBoolean;
|
||||
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
/**
|
||||
* A game object hosts the shared data associated with a game played by one or more players. The
|
||||
* game object extends the place object so that the game can act as a place where players actually
|
||||
* go when playing the game. Only very basic information is maintained in the base game object. It
|
||||
* serves as the base for a hierarchy of game object derivatives that handle basic gameplay for a
|
||||
* suite of different game types (ie. turn based games, party games, board games, card games,
|
||||
* etc.).
|
||||
*/
|
||||
public class GameObject extends PlaceObject
|
||||
{
|
||||
// AUTO-GENERATED: FIELDS START
|
||||
/** The field name of the <code>state</code> field. */
|
||||
public static const STATE :String = "state";
|
||||
|
||||
/** The field name of the <code>isRated</code> field. */
|
||||
public static const IS_RATED :String = "isRated";
|
||||
|
||||
/** The field name of the <code>isPrivate</code> field. */
|
||||
public static const IS_PRIVATE :String = "isPrivate";
|
||||
|
||||
/** The field name of the <code>players</code> field. */
|
||||
public static const PLAYERS :String = "players";
|
||||
|
||||
/** The field name of the <code>winners</code> field. */
|
||||
public static const WINNERS :String = "winners";
|
||||
|
||||
/** The field name of the <code>sessionId</code> field. */
|
||||
public static const SESSION_ID :String = "sessionId";
|
||||
|
||||
/** The field name of the <code>playerStatus</code> field. */
|
||||
public static const PLAYER_STATUS :String = "playerStatus";
|
||||
// AUTO-GENERATED: FIELDS END
|
||||
|
||||
/** A game state constant indicating that the game has not yet started and is still awaiting
|
||||
* the arrival of all of the players. */
|
||||
public static const PRE_GAME :int = 0;
|
||||
|
||||
/** A game state constant indicating that the game is in play. */
|
||||
public static const IN_PLAY :int = 1;
|
||||
|
||||
/** A game state constant indicating that the game ended normally. */
|
||||
public static const GAME_OVER :int = 2;
|
||||
|
||||
/** A game state constant indicating that the game was cancelled. */
|
||||
public static const CANCELLED :int = 3;
|
||||
|
||||
/** The player status constant for a player whose game is in play. */
|
||||
public static const PLAYER_IN_PLAY :int = 0;
|
||||
|
||||
/** The player status constant for a player whose has been knocked out of the game. NOTE: This
|
||||
* can include a player choosing to leave a game prematurely. */
|
||||
public static const PLAYER_LEFT_GAME :int = 1;
|
||||
|
||||
/** The game state, one of {@link #PRE_GAME}, {@link #IN_PLAY}, {@link #GAME_OVER}, or
|
||||
* {@link #CANCELLED}. */
|
||||
public var state :int = PRE_GAME;
|
||||
|
||||
/** Indicates whether or not this game is rated. */
|
||||
public var isRated :Boolean;
|
||||
|
||||
/** Indicates whether the game is "private". */
|
||||
public var isPrivate :Boolean;
|
||||
|
||||
/** The usernames of the players involved in this game. */
|
||||
public var players :TypedArray; /* of Name */
|
||||
|
||||
/** Whether each player in the game is a winner, or null if the game is not yet over. */
|
||||
public var winners :TypedArray; /* of Boolean */
|
||||
|
||||
/** A unique identifier for each game session. Every time the game is started, this value will
|
||||
* be incremented to provide a unique identifier for that particular session. */
|
||||
public var sessionId :int;
|
||||
|
||||
/** If null, indicates that all present players are active, or for more complex games can be
|
||||
* non-null to indicate the current status of each player in the game. The status value is one
|
||||
* of {@link #PLAYER_LEFT_GAME} or {@link #PLAYER_IN_PLAY}. */
|
||||
public var playerStatus :TypedArray; /* of int */
|
||||
|
||||
/**
|
||||
* Returns the number of players in the game.
|
||||
*/
|
||||
public function getPlayerCount () :int
|
||||
{
|
||||
var count :int = 0;
|
||||
var size :int = players.length;
|
||||
for (var ii :int = 0; ii < size; ii++) {
|
||||
if (players[ii] != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of active players in the game.
|
||||
*/
|
||||
public function getActivePlayerCount () :int
|
||||
{
|
||||
var count :int = 0;
|
||||
var size :int = players.length;
|
||||
for (var ii :int = 0; ii < size; ii++) {
|
||||
if (isActivePlayer(ii)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given player is still an active player in the game. (Ie. whether or not
|
||||
* they are still participating.)
|
||||
*/
|
||||
public function isActivePlayer (pidx :int) :Boolean
|
||||
{
|
||||
return isOccupiedPlayer(pidx) &&
|
||||
(playerStatus == null || isActivePlayerStatus(playerStatus[pidx]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player index of the given user in the game, or <code>-1</code> if the player is
|
||||
* not involved in the game.
|
||||
*/
|
||||
public function getPlayerIndex (username :Name) :int
|
||||
{
|
||||
return Arrays.indexOf(players, username);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the game is in play. A game that is not in play could either be awaiting
|
||||
* players, ended, or cancelled.
|
||||
*/
|
||||
public function isInPlay () :Boolean
|
||||
{
|
||||
return (state == IN_PLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given player index in the game is occupied.
|
||||
*/
|
||||
public function isOccupiedPlayer (pidx :int) :Boolean
|
||||
{
|
||||
return (pidx >= 0 && pidx < players.length) && (players[pidx] != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given player index is a winner, or false if the winners are not yet
|
||||
* assigned.
|
||||
*/
|
||||
public function isWinner (pidx :int) :Boolean
|
||||
{
|
||||
return (winners != null) && winners[pidx];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of winners for this game, or <code>0</code> if the winners array is not
|
||||
* populated, e.g., the game is not yet over.
|
||||
*/
|
||||
public function getWinnerCount () :int
|
||||
{
|
||||
var count :int = 0;
|
||||
if (winners != null) {
|
||||
for (var ii :int = 0; ii < winners.length; ii++) {
|
||||
if (winners[ii]) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the game is ended in a draw.
|
||||
*/
|
||||
public function isDraw () :Boolean
|
||||
{
|
||||
return getWinnerCount() == getPlayerCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the winner index of the first winning player for this game, or <code>-1</code> if
|
||||
* there are no winners or the winners array is not yet assigned. This is only likely to be
|
||||
* useful for games that are known to have a single winner.
|
||||
*/
|
||||
public function getWinnerIndex () :int
|
||||
{
|
||||
return Arrays.indexOf(winners, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by {@link #isActivePlayer} to determine if the supplied status is associated with an
|
||||
* active player (one that has not resigned from the game and/or left the game room).
|
||||
*/
|
||||
protected function isActivePlayerStatus (playerStatus :int) :Boolean
|
||||
{
|
||||
return playerStatus == PLAYER_IN_PLAY;
|
||||
}
|
||||
|
||||
override protected function whichJoiner (j :Joiner) :void
|
||||
{
|
||||
super.whichJoiner(j);
|
||||
j.addArgs("(" + players.join() + ")", state);
|
||||
}
|
||||
|
||||
// // AUTO-GENERATED: METHODS START
|
||||
// /**
|
||||
// * Requests that the <code>state</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setState (value :int) :void
|
||||
// {
|
||||
// var ovalue :int = this.state;
|
||||
// requestAttributeChange(
|
||||
// STATE, Integer.valueOf(value), Integer.valueOf(ovalue));
|
||||
// this.state = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>isRated</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setIsRated (value :Boolean) :void
|
||||
// {
|
||||
// var ovalue :Boolean = this.isRated;
|
||||
// requestAttributeChange(
|
||||
// IS_RATED, langBoolean.valueOf(value), langBoolean.valueOf(ovalue));
|
||||
// this.isRated = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>isPrivate</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setIsPrivate (value :Boolean) :void
|
||||
// {
|
||||
// var ovalue :Boolean = this.isPrivate;
|
||||
// requestAttributeChange(
|
||||
// IS_PRIVATE, langBoolean.valueOf(value),
|
||||
// langBoolean.valueOf(ovalue));
|
||||
// this.isPrivate = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>players</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setPlayers (value :TypedArray) :void
|
||||
// {
|
||||
// var ovalue :TypedArray = this.players;
|
||||
// requestAttributeChange(
|
||||
// PLAYERS, value, ovalue);
|
||||
// this.players = (value == null) ? null : (value.clone() as TypedArray);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>index</code>th element of
|
||||
// * <code>players</code> field be set to the specified value.
|
||||
// * The local value will be updated immediately and an event will be
|
||||
// * propagated through the system to notify all listeners that the
|
||||
// * attribute did change. Proxied copies of this object (on clients)
|
||||
// * will apply the value change when they received the attribute
|
||||
// * changed notification.
|
||||
// */
|
||||
// public function setPlayersAt (value :Name, index :int) :void
|
||||
// {
|
||||
// var ovalue :Name = (this.players[index] as Name);
|
||||
// requestElementUpdate(
|
||||
// PLAYERS, index, value, ovalue);
|
||||
// this.players[index] = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>winners</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setWinners (value :TypedArray) :void
|
||||
// {
|
||||
// var ovalue :TypedArray = this.winners;
|
||||
// requestAttributeChange(
|
||||
// WINNERS, value, ovalue);
|
||||
// this.winners = (value == null) ? null : (value.clone() as TypedArray);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>index</code>th element of
|
||||
// * <code>winners</code> field be set to the specified value.
|
||||
// * The local value will be updated immediately and an event will be
|
||||
// * propagated through the system to notify all listeners that the
|
||||
// * attribute did change. Proxied copies of this object (on clients)
|
||||
// * will apply the value change when they received the attribute
|
||||
// * changed notification.
|
||||
// */
|
||||
// public function setWinnersAt (value :Boolean, index :int) :void
|
||||
// {
|
||||
// var ovalue :Boolean = (this.winners[index] as Boolean);
|
||||
// requestElementUpdate(
|
||||
// WINNERS, index, langBoolean.valueOf(value),
|
||||
// langBoolean.valueOf(ovalue));
|
||||
// this.winners[index] = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>sessionId</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setSessionId (value :int) :void
|
||||
// {
|
||||
// var ovalue :int = this.sessionId;
|
||||
// requestAttributeChange(
|
||||
// SESSION_ID, Integer.valueOf(value), Integer.valueOf(ovalue));
|
||||
// this.sessionId = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>playerStatus</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// public function setPlayerStatus (value :TypedArray) :void
|
||||
// {
|
||||
// var ovalue :TypedArray = this.playerStatus;
|
||||
// requestAttributeChange(
|
||||
// PLAYER_STATUS, value, ovalue);
|
||||
// this.playerStatus = (value == null) ? null
|
||||
// : (value.clone() as TypedArray);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>index</code>th element of
|
||||
// * <code>playerStatus</code> field be set to the specified value.
|
||||
// * The local value will be updated immediately and an event will be
|
||||
// * propagated through the system to notify all listeners that the
|
||||
// * attribute did change. Proxied copies of this object (on clients)
|
||||
// * will apply the value change when they received the attribute
|
||||
// * changed notification.
|
||||
// */
|
||||
// public function setPlayerStatusAt (value :int, index :int) :void
|
||||
// {
|
||||
// var ovalue :int = (this.playerStatus[index] as int);
|
||||
// requestElementUpdate(
|
||||
// PLAYER_STATUS, index, Integer.valueOf(value),
|
||||
// Integer.valueOf(ovalue));
|
||||
// this.playerStatus[index] = value;
|
||||
// }
|
||||
// // AUTO-GENERATED: METHODS END
|
||||
//
|
||||
// override public function writeObject (out :ObjectOutputStream) :void
|
||||
// {
|
||||
// super.writeObject(out);
|
||||
//
|
||||
// out.writeObject(gameService);
|
||||
// out.writeInt(state);
|
||||
// out.writeBoolean(isRated);
|
||||
// out.writeBoolean(isPrivate);
|
||||
// out.writeObject(players);
|
||||
// out.writeField(winners);
|
||||
// out.writeInt(sessionId);
|
||||
// out.writeField(playerStatus);
|
||||
// }
|
||||
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
|
||||
state = ins.readInt();
|
||||
isRated = ins.readBoolean();
|
||||
isPrivate = ins.readBoolean();
|
||||
players = TypedArray(ins.readObject());
|
||||
winners = (ins.readField(TypedArray.getJavaType(Boolean)) as TypedArray);
|
||||
sessionId = ins.readInt();
|
||||
playerStatus = (ins.readField(TypedArray.getJavaType(int)) as TypedArray);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.game.data {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
public class UserIdentifier
|
||||
{
|
||||
/**
|
||||
* Get the user id for the specified user, or 0 if they're not valid.
|
||||
*/
|
||||
public static function getUserId (name :Name) :int
|
||||
{
|
||||
return (_userIder == null) ? 0 : _userIder(name);
|
||||
}
|
||||
|
||||
public static function setIder (userIder :Function) :void
|
||||
{
|
||||
_userIder = userIder;
|
||||
}
|
||||
|
||||
protected static var _userIder :Function;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.turn.client {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Games that wish to make use of the turn game services should have their
|
||||
* controller implement this interface and create an instance of {@link
|
||||
* TurnGameControllerDelegate} which should be passed to {@link
|
||||
* GameController#addDelegate}.
|
||||
*/
|
||||
public interface TurnGameController
|
||||
{
|
||||
/**
|
||||
* Called when the turn changed. This indicates the start of a turn
|
||||
* and the user interface should adjust itself accordingly (activating
|
||||
* controls if it is our turn and deactivating them if it is not).
|
||||
*
|
||||
* @param turnHolder the username of the new holder of the turn.
|
||||
*/
|
||||
function turnDidChange (turnHolder :Name) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.turn.client {
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.parlor.game.client.GameController;
|
||||
import com.threerings.parlor.game.client.GameControllerDelegate;
|
||||
import com.threerings.parlor.game.data.GameObject;
|
||||
import com.threerings.parlor.turn.data.TurnGameObject;
|
||||
|
||||
/**
|
||||
* Performs the client-side processing for a turn-based game. Games which
|
||||
* wish to make use of these services must construct a delegate and call
|
||||
* out to it at the appropriate times (see the method documentation for
|
||||
* which methods should be called when). The game's controller must also
|
||||
* implement the {@link TurnGameController} interface so that it can be
|
||||
* notified when turn-based game events take place.
|
||||
*/
|
||||
public class TurnGameControllerDelegate extends GameControllerDelegate
|
||||
implements AttributeChangeListener
|
||||
{
|
||||
/** A special value used to communicate to the client that the current
|
||||
* turn holder was replaced (perhaps due to disconnection or departure
|
||||
* and being replaced by an AI). */
|
||||
public static const TURN_HOLDER_REPLACED :Name =
|
||||
new Name("__TURN_HOLDER_REPLACED__");
|
||||
|
||||
/**
|
||||
* Constructs a delegate which will call back to the supplied {@link
|
||||
* TurnGameController} implementation wen turn-based game related
|
||||
* things happen.
|
||||
*/
|
||||
public function TurnGameControllerDelegate (tgctrl :TurnGameController)
|
||||
{
|
||||
super(GameController(tgctrl));
|
||||
|
||||
// keep this around for later
|
||||
_tgctrl = tgctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the game is in progress and it is our turn; false
|
||||
* otherwise.
|
||||
*/
|
||||
public function isOurTurn () :Boolean
|
||||
{
|
||||
var self :BodyObject =
|
||||
(_ctx.getClient().getClientObject() as BodyObject);
|
||||
return (_gameObj.isInPlay() &&
|
||||
self.getVisibleName().equals(_turnGame.getTurnHolder()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the current turn holder as configured in the
|
||||
* game object.
|
||||
*
|
||||
* @return the index into the players array of the current turn holder
|
||||
* or -1 if there is no current turn holder.
|
||||
*/
|
||||
public function getTurnHolderIndex () :int
|
||||
{
|
||||
return _gameObj.getPlayerIndex(_turnGame.getTurnHolder());
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function init (ctx :CrowdContext, config :PlaceConfig) :void
|
||||
{
|
||||
_ctx = ctx;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function willEnterPlace (plobj :PlaceObject) :void
|
||||
{
|
||||
// get a casted reference to the object
|
||||
_gameObj = (plobj as GameObject);
|
||||
_turnGame = (plobj as TurnGameObject);
|
||||
_thfield = _turnGame.getTurnHolderFieldName();
|
||||
|
||||
// and add ourselves as a listener
|
||||
plobj.addListener(this);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function didLeavePlace (plobj :PlaceObject) :void
|
||||
{
|
||||
// remove our listenership
|
||||
plobj.removeListener(this);
|
||||
|
||||
// clean up
|
||||
_turnGame = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function attributeChanged (event :AttributeChangedEvent) :void
|
||||
{
|
||||
// handle turn changes
|
||||
if (event.getName() == _thfield) {
|
||||
var name :Name = (event.getValue() as Name);
|
||||
var oname :Name = (event.getOldValue() as Name);
|
||||
if (TURN_HOLDER_REPLACED.equals(name) ||
|
||||
TURN_HOLDER_REPLACED.equals(oname)) {
|
||||
// small hackery: ignore the turn holder being set to
|
||||
// TURN_HOLDER_REPLACED as it means that we're replacing
|
||||
// the current turn holder rather than switching turns;
|
||||
// also ignore the new turn holder when we switch from THR
|
||||
// to a real name again
|
||||
} else {
|
||||
_tgctrl.turnDidChange(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The turn game controller for whom we are delegating. */
|
||||
protected var _tgctrl :TurnGameController;
|
||||
|
||||
/** A reference to our client context. */
|
||||
protected var _ctx :CrowdContext;
|
||||
|
||||
/** A reference to our game object. */
|
||||
protected var _gameObj :GameObject;
|
||||
|
||||
/** A casted reference to our game object as a turn game. */
|
||||
protected var _turnGame :TurnGameObject;
|
||||
|
||||
/** The name of the turn holder field. */
|
||||
protected var _thfield :String;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.turn.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Games that wish to support turn-based play must implement this
|
||||
* interface with their {@link GameObject}.
|
||||
*/
|
||||
public interface TurnGameObject
|
||||
{
|
||||
/**
|
||||
* Returns the distributed object field name of the
|
||||
* <code>turnHolder</code> field in the object that implements this
|
||||
* interface.
|
||||
*/
|
||||
function getTurnHolderFieldName () :String;
|
||||
|
||||
/**
|
||||
* Returns the username of the player who is currently taking their
|
||||
* turn in this turn-based game or <code>null</code> if no user
|
||||
* currently holds the turn.
|
||||
*/
|
||||
function getTurnHolder () :Name;
|
||||
|
||||
// /**
|
||||
// * Requests that the <code>turnHolder</code> field be set to the specified
|
||||
// * value.
|
||||
// */
|
||||
// function setTurnHolder (turnHolder :Name) :void;
|
||||
|
||||
/**
|
||||
* Returns the array of player names involved in the game.
|
||||
*/
|
||||
function getPlayers () :TypedArray /* of Name */;
|
||||
|
||||
/**
|
||||
* Returns true if the game is in play, false if not. If a game is not in
|
||||
* play after a turn has ended, the next turn will not be started.
|
||||
*/
|
||||
function isInPlay () :Boolean;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.parlor.util {
|
||||
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.parlor.client.ParlorDirector;
|
||||
|
||||
/**
|
||||
* The parlor context provides access to the various managers, etc. that
|
||||
* are needed by the parlor client code.
|
||||
*/
|
||||
public interface ParlorContext extends CrowdContext
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the parlor director.
|
||||
*/
|
||||
function getParlorDirector () :ParlorDirector;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
import flash.display.Sprite;
|
||||
|
||||
import as3isolib.display.IsoSprite;
|
||||
|
||||
import com.threerings.util.DirectionCodes;
|
||||
|
||||
import com.threerings.media.util.Path;
|
||||
import com.threerings.media.util.Pathable;
|
||||
|
||||
import com.threerings.cast.CharacterSprite;
|
||||
|
||||
import com.threerings.miso.client.PriorityIsoDisplayObject;
|
||||
import com.threerings.miso.util.MisoSceneMetrics;
|
||||
import com.threerings.miso.util.MisoUtil;
|
||||
|
||||
import com.threerings.stage.data.StageLocation;
|
||||
|
||||
public class CharacterIsoSprite extends IsoSprite
|
||||
implements Pathable, PriorityIsoDisplayObject
|
||||
{
|
||||
public function CharacterIsoSprite (bodyOid :int, metrics :MisoSceneMetrics,
|
||||
charSprite :CharacterSprite)
|
||||
{
|
||||
_metrics = metrics;
|
||||
_bodyOid = bodyOid;
|
||||
setSize(1, 1, 2);
|
||||
|
||||
usePreciseValues = true;
|
||||
|
||||
// We wrap the sprite so we can shift it where we need it. Components like to line up
|
||||
// to the middle of a tile and as3isolib likes to line up to the back of a tile.
|
||||
var wrapper :Sprite = new Sprite();
|
||||
wrapper.y = _metrics.tilehhei;
|
||||
wrapper.addChild(charSprite);
|
||||
|
||||
_character = charSprite;
|
||||
|
||||
sprites = [wrapper];
|
||||
}
|
||||
|
||||
public function tick (tickStamp :int) :void
|
||||
{
|
||||
if (_path != null) {
|
||||
if (_pathStamp == 0) {
|
||||
_pathStamp = tickStamp
|
||||
_path.init(this, _pathStamp);
|
||||
}
|
||||
if (_path != null) {
|
||||
_path.tick(this, tickStamp);
|
||||
}
|
||||
}
|
||||
_character.tick(tickStamp);
|
||||
}
|
||||
|
||||
public function isMoving () :Boolean
|
||||
{
|
||||
return _path != null;
|
||||
}
|
||||
|
||||
public function getBodyOid () :int
|
||||
{
|
||||
return _bodyOid;
|
||||
}
|
||||
|
||||
public function placeAtLoc (loc :StageLocation) :void
|
||||
{
|
||||
setLocation(MisoUtil.fullToTile(loc.x), MisoUtil.fullToTile(loc.y));
|
||||
setOrientation(loc.orient);
|
||||
}
|
||||
|
||||
public function getX () :Number
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public function getY () :Number
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public function setLocation (x :Number, y :Number) :void
|
||||
{
|
||||
moveTo(x, y, 0);
|
||||
}
|
||||
|
||||
public function setOrientation (orient :int) :void
|
||||
{
|
||||
_character.setOrientation(toIsoOrient(orient));
|
||||
}
|
||||
|
||||
public function toIsoOrient (orient :int) :int
|
||||
{
|
||||
if (orient == DirectionCodes.NONE) {
|
||||
return orient;
|
||||
} else {
|
||||
return (orient + 2) % 8;
|
||||
}
|
||||
}
|
||||
|
||||
public function fromIsoOrient (orient :int) :int
|
||||
{
|
||||
if (orient == DirectionCodes.NONE) {
|
||||
return orient;
|
||||
} else {
|
||||
return (orient + 6) % 8;
|
||||
}
|
||||
}
|
||||
|
||||
public function getOrientation () :int
|
||||
{
|
||||
return fromIsoOrient(_character.getOrientation());
|
||||
}
|
||||
|
||||
public function pathBeginning () :void
|
||||
{
|
||||
_character.pathBeginning();
|
||||
}
|
||||
|
||||
public function pathCompleted (timestamp :int) :void
|
||||
{
|
||||
_character.pathCompleted(timestamp);
|
||||
var opath :Path = _path;
|
||||
_path = null;
|
||||
|
||||
for each (var listener :Function in _pathCompleteListeners) {
|
||||
listener(this, opath, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
public function addPathCompleteListener (listener :Function) :void
|
||||
{
|
||||
_pathCompleteListeners.push(listener);
|
||||
}
|
||||
|
||||
public function move (path :Path) :void
|
||||
{
|
||||
// if there's a previous path, let it know that it's going away
|
||||
cancelMove();
|
||||
|
||||
// save off this path
|
||||
_path = path;
|
||||
|
||||
// we'll initialize it on our next tick thanks to a zero path stamp
|
||||
_pathStamp = 0;
|
||||
}
|
||||
|
||||
public function cancelMove () :void
|
||||
{
|
||||
if (_path != null) {
|
||||
var oldpath :Path = _path;
|
||||
_path = null;
|
||||
oldpath.wasRemoved(this);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPriority () :int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function hitTest (stageX :int, stageY :int) :Boolean
|
||||
{
|
||||
return _character == null ? false : _character.hitTest(stageX, stageY);
|
||||
}
|
||||
|
||||
protected var _bodyOid :int;
|
||||
|
||||
protected var _metrics :MisoSceneMetrics;
|
||||
|
||||
protected var _character :CharacterSprite;
|
||||
|
||||
/** Path we're currently following, if any. */
|
||||
protected var _path :Path;
|
||||
|
||||
/** The time we started moving on our path. */
|
||||
protected var _pathStamp :int;
|
||||
|
||||
/** Anyone who cares when our path finishes. */
|
||||
protected var _pathCompleteListeners :Array = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import flash.geom.Point;
|
||||
|
||||
import com.threerings.whirled.spot.data.Cluster;
|
||||
|
||||
public class ClusterClickedInfo
|
||||
{
|
||||
/** The description of the cluster in question. */
|
||||
public var cluster :Cluster;
|
||||
|
||||
/** The point which was clicked. */
|
||||
public var loc :Point;
|
||||
|
||||
public function ClusterClickedInfo (cluster :Cluster, loc :Point)
|
||||
{
|
||||
this.cluster = cluster;
|
||||
this.loc = loc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,814 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import flash.events.Event;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.geom.Point;
|
||||
|
||||
import as3isolib.geom.Pt;
|
||||
|
||||
import com.threerings.util.Controller;
|
||||
import com.threerings.util.Iterator;
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
import com.threerings.util.Maps;
|
||||
import com.threerings.util.MathUtil;
|
||||
import com.threerings.util.StringUtil;
|
||||
|
||||
import com.threerings.presents.dobj.EntryUpdatedEvent;
|
||||
import com.threerings.presents.dobj.SetAdapter;
|
||||
import com.threerings.presents.dobj.SetListener;
|
||||
|
||||
import com.threerings.crowd.client.OccupantObserver;
|
||||
import com.threerings.crowd.data.OccupantInfo;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.media.Tickable;
|
||||
import com.threerings.media.util.LineSegmentPath;
|
||||
import com.threerings.media.util.Path;
|
||||
|
||||
import com.threerings.cast.CharacterSprite;
|
||||
|
||||
import com.threerings.miso.util.MisoSceneMetrics;
|
||||
import com.threerings.miso.util.MisoUtil;
|
||||
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
import com.threerings.whirled.spot.data.SceneLocation;
|
||||
import com.threerings.whirled.spot.data.SpotCodes;
|
||||
import com.threerings.whirled.spot.data.SpotSceneObject;
|
||||
|
||||
import com.threerings.stage.data.StageLocation;
|
||||
import com.threerings.stage.data.StageSceneObject;
|
||||
import com.threerings.stage.util.StageContext;
|
||||
|
||||
public class CrowdStageScenePanel extends StageScenePanel
|
||||
implements OccupantObserver, Tickable
|
||||
{
|
||||
private var log :Log = Log.getLog(CrowdStageScenePanel);
|
||||
|
||||
public function CrowdStageScenePanel (sCtx :StageContext, cCtx :CrowdContext, ctrl :Controller,
|
||||
metrics :MisoSceneMetrics)
|
||||
{
|
||||
super(sCtx, ctrl, metrics);
|
||||
|
||||
_cCtx = cCtx;
|
||||
|
||||
// compute our proximity radius (one visible screen diagonal);
|
||||
// also don't let it shrink when we're birded
|
||||
_proxrad = int(Math.max(_proxrad, Math.sqrt(_isoView.size.x*_isoView.size.x +
|
||||
_isoView.size.y*_isoView.size.y)));
|
||||
recomputeProximate();
|
||||
}
|
||||
|
||||
override public function willEnterPlace (plObj :PlaceObject) :void
|
||||
{
|
||||
super.willEnterPlace(plObj);
|
||||
_scObj = StageSceneObject(plObj);
|
||||
plObj.addListener(_occupantListener);
|
||||
_cCtx.getOccupantDirector().addOccupantObserver(this);
|
||||
updateDisplayForScene();
|
||||
}
|
||||
|
||||
override public function tick (tickStamp :int) :void
|
||||
{
|
||||
super.tick(tickStamp);
|
||||
var shouldRender :Boolean = false;
|
||||
_sprites.forEach(function (key :int, sprite :CharacterIsoSprite) :void {
|
||||
sprite.tick(tickStamp);
|
||||
shouldRender ||= sprite.isInvalidated;
|
||||
});
|
||||
|
||||
// TODO - partial scene rerenders would be useful here...
|
||||
if (shouldRender) {
|
||||
_objScene.render();
|
||||
}
|
||||
}
|
||||
|
||||
protected function updateDisplayForScene () :void
|
||||
{
|
||||
// remove all old-scene sprites
|
||||
clearAllSprites();
|
||||
|
||||
// fake an occupant entry for all scene occupants
|
||||
for each (var occupantInfo :OccupantInfo in _scObj.occupantInfo.toArray()) {
|
||||
occupantEntered(occupantInfo);
|
||||
}
|
||||
|
||||
// start out with the view centered on our sprite so that we
|
||||
// resolve the appropriate scene blocks from the get go
|
||||
centerView(true, false);
|
||||
}
|
||||
|
||||
protected function centerView (immediate :Boolean, optional :Boolean) :void
|
||||
{
|
||||
if (_selfSprite != null) {
|
||||
var viewPt :Point =
|
||||
_isoView.isoToLocal(new Pt(_selfSprite.x, _selfSprite.y, _selfSprite.z));
|
||||
|
||||
var dx :int = viewPt.x - _isoView.width / 2;
|
||||
var dy :int = viewPt.y - _isoView.height / 2;
|
||||
|
||||
// Unless we've forced it, if we'd move less than a quarter screen, don't bother.
|
||||
if (!optional || Math.abs(dx) > _isoView.width / 4 ||
|
||||
Math.abs(dy) > _isoView.height / 4) {
|
||||
moveBy(new Point(dx, dy), immediate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all the sprites from the scene, even our own.
|
||||
*/
|
||||
protected function clearAllSprites () :void
|
||||
{
|
||||
// clear the actual sprites
|
||||
//TODO clearSprites();
|
||||
|
||||
// and clear all of our wacky lists
|
||||
_sprites.clear();
|
||||
_arriveLists.clear();
|
||||
_pendingRemoveSprites.clear();
|
||||
}
|
||||
|
||||
override public function didLeavePlace (plObj :PlaceObject) :void
|
||||
{
|
||||
super.didLeavePlace(plObj);
|
||||
plObj.removeListener(_occupantListener);
|
||||
_cCtx.getOccupantDirector().removeOccupantObserver(this);
|
||||
}
|
||||
|
||||
public function occupantEntered (info :OccupantInfo) :void
|
||||
{
|
||||
// we do mostly the same thing for entry and update
|
||||
occupantUpdated(null, info);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we arrive at our new location, all no longer proximate occupant's sprites are
|
||||
* booted and any newly proximate occupants have sprites created for them.
|
||||
*/
|
||||
protected function recomputeProximate () :void
|
||||
{
|
||||
if (_scObj == null) {
|
||||
return; // nothing doing!
|
||||
}
|
||||
|
||||
for each (var sloc :SceneLocation in _scObj.occupantLocs) {
|
||||
var sprite :CharacterIsoSprite = getSprite(sloc.bodyOid);
|
||||
if (isProximateToLoc(sloc)) {
|
||||
if (sprite == null) {
|
||||
// fake an update which will create their sprite
|
||||
occupantMoved(sloc, sloc, false);
|
||||
}
|
||||
} else if (sprite != null) {
|
||||
removeSprite(sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this occupant is proximate to ourself.
|
||||
*/
|
||||
public function isProximate (info :OccupantInfo) :Boolean
|
||||
{
|
||||
var sloc :SceneLocation = locationForBody(info.getBodyOid());
|
||||
return (sloc != null && isProximateToLoc(sloc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this user is close enough to us that we want to go to the trouble of
|
||||
* creating a sprite for them and all the business.
|
||||
*/
|
||||
protected function isProximateToLoc (sceneLoc :SceneLocation) :Boolean
|
||||
{
|
||||
// make sure we know where we are
|
||||
var mySceneLoc :SceneLocation = locationForBody(myOid());
|
||||
if (mySceneLoc == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// if they're within one screen diagonal of us, they're proximate
|
||||
var myLoc :StageLocation = StageLocation(mySceneLoc.loc);
|
||||
var loc :StageLocation = StageLocation(sceneLoc.loc);
|
||||
var pos :Point = _isoView.isoToLocal(new Pt(MisoUtil.fullToTile(loc.x),
|
||||
MisoUtil.fullToTile(loc.y), 0));
|
||||
var myPos :Point = _isoView.isoToLocal(new Pt(MisoUtil.fullToTile(myLoc.x),
|
||||
MisoUtil.fullToTile(myLoc.y), 0));
|
||||
return int(MathUtil.distance(pos.x, pos.y, myPos.x, myPos.y)) < _proxrad;
|
||||
}
|
||||
|
||||
public function occupantLeft (info :OccupantInfo) :void
|
||||
{
|
||||
// remove the occupant's sprite
|
||||
var oid :int = info.getBodyOid();
|
||||
if (oid == myOid()) {
|
||||
// never remove our own sprite!
|
||||
return;
|
||||
}
|
||||
|
||||
var sprite :CharacterIsoSprite = getSprite(oid);
|
||||
if (sprite == null) {
|
||||
if (isProximate(info)) {
|
||||
log.warning("Proximate occupant left, but no sprite to remove " + info + ".");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if they are already moving, stick them in the pending remove
|
||||
// table so that we give them the boot when they arrive at their destination
|
||||
if (sprite.isMoving()) {
|
||||
_pendingRemoveSprites.put(oid, sprite);
|
||||
return;
|
||||
}
|
||||
|
||||
// if the sprite is already at a portal, go ahead and remove them
|
||||
var sprLoc :Point = _isoView.localToIso(new Point(sprite.x, sprite.y));
|
||||
for (var iter :Iterator = _scene.getPortals(); iter.hasNext(); ) {
|
||||
var port :Portal = Portal(iter.next());
|
||||
var portLoc :StageLocation = StageLocation(port.loc);
|
||||
if (portLoc.x == sprLoc.x && portLoc.y == sprLoc.y) {
|
||||
removeSprite(sprite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// walk them to the default entrance; note: we have to put them in the pending table
|
||||
// *before* we call moveSprite because moveSprite might decide to immediately warp them to
|
||||
// their destination and call handleLocationArrived() directly which will expect them to be
|
||||
// in the pending table at that point
|
||||
_pendingRemoveSprites.put(oid, sprite);
|
||||
moveSpriteFromScene(sprite);
|
||||
}
|
||||
|
||||
public function occupantUpdated (oldinfo :OccupantInfo, newinfo :OccupantInfo) :void
|
||||
{
|
||||
var bodyOid :int = newinfo.getBodyOid();
|
||||
var sloc :SceneLocation = locationForBody(bodyOid);
|
||||
if (sloc == null || !isProximateToLoc(sloc)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// look up their character sprite
|
||||
var sprite :CharacterIsoSprite = getSprite(newinfo.getBodyOid());
|
||||
if (sprite == null) {
|
||||
// ...creating one if necessary
|
||||
sprite = createAndAddSprite(OccupantInfo(newinfo), null);
|
||||
// if we couldn't create the sprite for some reason, we can stop now
|
||||
if (sprite == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// ...updating it if we've already got one
|
||||
updateOccupantSprite(sprite, newinfo);
|
||||
|
||||
// make sure the sprite is no longer set to remove, in case it was
|
||||
_pendingRemoveSprites.remove(bodyOid);
|
||||
}
|
||||
|
||||
// if this is the first time they entered the scene, fake a move to their starting position
|
||||
if (oldinfo == null) {
|
||||
// fake a "moved" to their starting position
|
||||
occupantMoved(sloc, sloc, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs any updates required to the occupant's character sprite given the updated occupant
|
||||
* info.
|
||||
*/
|
||||
protected function updateOccupantSprite (sprite :CharacterIsoSprite, info :OccupantInfo) :void
|
||||
{
|
||||
// Nothing by default.
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an occupant has changed location. Updates clusters for this occupant and moves
|
||||
* their sprite.
|
||||
*/
|
||||
protected function occupantMoved (oloc :SceneLocation, nloc :SceneLocation,
|
||||
reallyMoved :Boolean) :void
|
||||
{
|
||||
var sprite :CharacterIsoSprite = getSprite(nloc.bodyOid);
|
||||
|
||||
// if their new location is not proximate, yank their sprite
|
||||
if (!isProximateToLoc(nloc)) {
|
||||
if (sprite != null) {
|
||||
// if they are visible, walk them to their new location
|
||||
if (_vbounds.intersects(sprite.getBounds(_isoView))) {
|
||||
moveSpriteToLoc(sprite, nloc.loc);
|
||||
}
|
||||
// now queue them up for removal on arrival as appropriate
|
||||
if (sprite.isMoving()) {
|
||||
_pendingRemoveSprites.put(nloc.bodyOid, sprite);
|
||||
} else {
|
||||
removeSprite(sprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now walk their sprite to its new location
|
||||
if (sprite == null) {
|
||||
var info :OccupantInfo = _cCtx.getOccupantDirector().getOccupantInfo(nloc.bodyOid);
|
||||
if (info != null) {
|
||||
sprite = createAndAddSprite(info, oloc);
|
||||
} else {
|
||||
log.warning("Can't update location of unknown '" + nloc + "' (" + who(nloc) + ").");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
moveSpriteToLoc(sprite, nloc.loc);
|
||||
|
||||
/*TODO Portals
|
||||
// if self going to a portal, use exiting mode.
|
||||
// if not-moving someone else to a portal, don't adjust mode
|
||||
// all other cases, set normal scene mode
|
||||
if (isPortal(nloc.loc)) {
|
||||
if (isMe) {
|
||||
sprite.setExiting();
|
||||
} else if (moving) {
|
||||
sprite.setNormalSceneMode();
|
||||
}
|
||||
} else {
|
||||
sprite.setNormalSceneMode();
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the sprite to the referenced location.
|
||||
*/
|
||||
protected function moveSpriteToLoc (sprite :CharacterIsoSprite, loc :Location) :void
|
||||
{
|
||||
var sloc :StageLocation = StageLocation(loc);
|
||||
// obtain the screen coordinates of the location
|
||||
|
||||
// if they're not already standing where we want them...
|
||||
if (sprite.x != sloc.x || sprite.y != sloc.y || sprite.isMoving()) {
|
||||
// ...move them there; but note whether they were put on a path or just warped
|
||||
// immediately
|
||||
if (!moveSprite(sprite, sloc)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if they're already there or they were warped there we want to invoke the arrival
|
||||
// processing
|
||||
handleSpriteArrived(sprite, new Date().time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the specified sprite to the specified screen coordinates along a tile path.
|
||||
*
|
||||
* @return true if the sprite was warped immediately to that position, false if they were set
|
||||
* upon a path to it.
|
||||
*/
|
||||
protected function moveSprite (sprite :CharacterIsoSprite, loc :StageLocation) :Boolean
|
||||
{
|
||||
var cx :int = sprite.x;
|
||||
var cy :int = sprite.y;
|
||||
var nx :int = MisoUtil.fullToTile(loc.x);
|
||||
var ny :int = MisoUtil.fullToTile(loc.y);
|
||||
|
||||
// if this panel is not yet showing, warp the sprite directly
|
||||
if (!visible) {
|
||||
sprite.cancelMove();
|
||||
sprite.placeAtLoc(loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if the source and destination are both offscreen, warp the
|
||||
// sprite to where they are going
|
||||
var sc :Point = _isoView.isoToLocal(new Pt(nx, ny, 0));
|
||||
var endsOff :Boolean = !_vbounds.contains(sc.x, sc.y);
|
||||
if (!_vbounds.intersects(sprite.getBounds(_isoView)) && endsOff) {
|
||||
sprite.cancelMove();
|
||||
sprite.placeAtLoc(loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if we are obviously warping (i.e. we moved a great distance),
|
||||
// just blink into position and attempt to do so cleanly
|
||||
var dx :int = Math.abs(nx - (_vbounds.x + _vbounds.width/2));
|
||||
var dy :int = Math.abs(ny - (_vbounds.y + _vbounds.height/2));
|
||||
if ((dx > 2*_vbounds.width || dy > 2*_vbounds.height) &&
|
||||
(sprite == _selfSprite)) {
|
||||
log.info("Warp-a-saurus! " + StringUtil.toString(_vbounds) +
|
||||
" -> " + StringUtil.toCoordsString(loc.x, loc.y));
|
||||
|
||||
sprite.cancelMove();
|
||||
sprite.placeAtLoc(loc);
|
||||
|
||||
// delay repaint until we resolve our new blocks
|
||||
centerView(true, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
// if we made it this far, we can actually try to compute a path
|
||||
// for this sprite; if the end of the path is off-screen, allow "partial" paths
|
||||
var path :LineSegmentPath = LineSegmentPath(getPath(sprite, nx, ny, endsOff));
|
||||
if (path == null) {
|
||||
log.info("Unable to compute path from " +
|
||||
StringUtil.toCoordsString(cx, cy) + " to " +
|
||||
StringUtil.toCoordsString(nx, ny) + "; warping.");
|
||||
|
||||
sprite.cancelMove();
|
||||
sprite.placeAtLoc(loc);
|
||||
return true;
|
||||
}
|
||||
|
||||
// set the sprite on a path to their new location
|
||||
path.setVelocity(SPRITE_PATH_VELOCITY);
|
||||
sprite.move(path);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate a sprite leaving the scene.
|
||||
*/
|
||||
protected function moveSpriteFromScene (sprite :CharacterIsoSprite) :void
|
||||
{
|
||||
moveSpriteToLoc(sprite, _scene.getDefaultEntrance().getLocation());
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for getting our OID.
|
||||
*/
|
||||
protected function myOid () :int
|
||||
{
|
||||
return _cCtx.getClient().getClientObject().getOid();
|
||||
}
|
||||
|
||||
protected function who (loc :SceneLocation) :String
|
||||
{
|
||||
var oinfo :OccupantInfo = OccupantInfo(_scObj.occupantInfo.get(loc.bodyOid));
|
||||
return (oinfo == null) ? ("" + loc.bodyOid) : oinfo.username.toString();
|
||||
}
|
||||
|
||||
protected function createAndAddSprite (info :OccupantInfo,
|
||||
loc :SceneLocation) :CharacterIsoSprite
|
||||
{
|
||||
var sprite :CharacterIsoSprite = createSprite(info);
|
||||
|
||||
// stick them in the appropriate location
|
||||
if (loc == null) {
|
||||
loc = locationForBody(info.getBodyOid());
|
||||
}
|
||||
if (loc == null) {
|
||||
log.warning("Requested to create sprite for locationless occupant " + info + ".",
|
||||
new Error());
|
||||
return null;
|
||||
}
|
||||
|
||||
// set their location and start tracking them
|
||||
sprite.placeAtLoc(StageLocation(loc.loc));
|
||||
|
||||
_objScene.addChild(sprite);
|
||||
_sprites.put(info.getBodyOid(), sprite);
|
||||
sprite.addPathCompleteListener(pathCompleted);
|
||||
|
||||
if (sprite.getBodyOid() == myOid()) {
|
||||
_selfSprite = sprite;
|
||||
}
|
||||
|
||||
return sprite;
|
||||
}
|
||||
|
||||
override public function handleMousePressed (hobject :Object, event :MouseEvent) :Boolean
|
||||
{
|
||||
var viewPt :Point = _isoView.globalToLocal(new Point(event.stageX, event.stageY));
|
||||
var iso :Point = _isoView.localToIso(new Point(viewPt.x, viewPt.y));
|
||||
|
||||
if (hobject is CharacterIsoSprite) {
|
||||
handleSpriteClicked(CharacterIsoSprite(hobject));
|
||||
return true;
|
||||
} else if (hobject is PortalIsoSprite) {
|
||||
handlePortalClicked(PortalIsoSprite(hobject).getPortal());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move ourselves to the spot clicked.
|
||||
handleLocationClicked(new StageLocation(MisoUtil.tileToFull(iso.x),
|
||||
MisoUtil.tileToFull(iso.y), 0));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function handlePortalClicked (portal :Portal) :void
|
||||
{
|
||||
// if the portal goes to the same scene, we do some special stuff
|
||||
if (portal.targetSceneId == _scene.getId()) {
|
||||
var tport :Portal = _scene.getPortal(portal.targetPortalId);
|
||||
if (tport == null) {
|
||||
log.warning("Requested to warp via bogus portal? " + portal);
|
||||
return;
|
||||
}
|
||||
|
||||
// start walking there and issue a request to walk there to
|
||||
// let everyone else know that we're walking there
|
||||
var ploc :StageLocation = StageLocation(portal.getLocation());
|
||||
moveSprite(_selfSprite, ploc);
|
||||
changeLocation(ploc);
|
||||
|
||||
// when we arrive at the first portal, issue a request to "warp" to the other one
|
||||
addArrivalListener(
|
||||
myOid(), ploc, function (sprite :CharacterIsoSprite, sloc :Location) :void {
|
||||
changeLocation(StageLocation(tport.getOppLocation()));
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, traverse the portal like a civilized pirate: start
|
||||
// walking toward it, and immediately issue the traversal request
|
||||
log.info("Traversing " + portal + " from " + _scene.getId() + ".");
|
||||
moveSprite(_selfSprite, StageLocation(portal.getLocation()));
|
||||
traversePortal(portal);
|
||||
}
|
||||
|
||||
protected function handleSpriteClicked (sprite :CharacterIsoSprite) :void
|
||||
{
|
||||
// Nothing by default.
|
||||
}
|
||||
|
||||
protected function displayFeedback (msg :String) :void
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
public function handleLocationClicked (loc :StageLocation) :void
|
||||
{
|
||||
// normalize the click to the center of the clicked tile and check
|
||||
// to see if it is occupied
|
||||
var tx :int = MisoUtil.fullToTile(loc.x);
|
||||
var ty :int = MisoUtil.fullToTile(loc.y);
|
||||
loc.x = MisoUtil.tileToFull(tx, 2);
|
||||
loc.y = MisoUtil.tileToFull(ty, 2);
|
||||
|
||||
if (tileOccupied(tx, ty, false)) {
|
||||
log.info("Not moving to occupied location " + loc + ".");
|
||||
displayFeedback(SpotCodes.INVALID_LOCATION);
|
||||
return;
|
||||
}
|
||||
|
||||
// see if we can walk there and what orientation we'd face once we got there
|
||||
var orient :int = checkWalkToLoc(loc);
|
||||
if (orient == -1) {
|
||||
// if the location is on a passable tile, let the user know why we rejected their click
|
||||
if (canTraverse(null, tx, ty)) {
|
||||
displayFeedback("m.cant_get_there");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// adjust the orientation and head there
|
||||
loc.orient = orient;
|
||||
changeLocation(loc);
|
||||
}
|
||||
|
||||
protected function changeLocation (loc :StageLocation) :void
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
protected function traversePortal (portal :Portal) :void
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the specified tile coordinate is occupied by any sprites or if the
|
||||
* specified tile is inside an existing cluster.
|
||||
*/
|
||||
protected function tileOccupied (tx :int, ty :int, countSelf :Boolean) :Boolean
|
||||
{
|
||||
var self :CharacterIsoSprite = getSprite(myOid());
|
||||
|
||||
// if we or the scene object is gone, don't freak out
|
||||
if (self == null || _scObj == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// next see if any room occupant is standing here
|
||||
for each (var loc :SceneLocation in _scObj.occupantLocs.toArray()) {
|
||||
if (!countSelf && loc.bodyOid == myOid()) {
|
||||
continue;
|
||||
}
|
||||
var sloc :StageLocation = StageLocation(loc.loc);
|
||||
if (MisoUtil.fullToTile(sloc.x) == tx && MisoUtil.fullToTile(sloc.y) == ty) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if we can compute a path to the specified location.
|
||||
*
|
||||
* @return the orientation the sprite would have upon arrival or -1 if
|
||||
* we cannot compute a path to the specified location.
|
||||
*/
|
||||
protected function checkWalkToLoc (loc :StageLocation) :int
|
||||
{
|
||||
// obtain the screen coordinates of the location
|
||||
var lx :int = MisoUtil.fullToTile(loc.x);
|
||||
var ly :int = MisoUtil.fullToTile(loc.y);
|
||||
|
||||
var us :CharacterIsoSprite = getSprite(myOid());
|
||||
if (us != null) {
|
||||
var path :LineSegmentPath = LineSegmentPath(getPath(us, lx, ly, false));
|
||||
return (path == null) ? -1 : path.getFinalOrientation();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected function createSprite (info :OccupantInfo) :CharacterIsoSprite
|
||||
{
|
||||
return new CharacterIsoSprite(info.getBodyOid(), _metrics, createCharacter(info));
|
||||
}
|
||||
|
||||
protected function createCharacter (info :OccupantInfo) :CharacterSprite
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
protected function getSprite (bodyOid :int) :CharacterIsoSprite
|
||||
{
|
||||
return _sprites.get(bodyOid);
|
||||
}
|
||||
|
||||
protected function removeSprite (sprite :CharacterIsoSprite) :void
|
||||
{
|
||||
_sprites.remove(sprite.getBodyOid());
|
||||
_objScene.removeChild(sprite);
|
||||
}
|
||||
|
||||
protected function handleSpriteArrived (sprite :CharacterIsoSprite, tickStamp :int) :void
|
||||
{
|
||||
var oid :int = sprite.getBodyOid();
|
||||
|
||||
var alist :ArrivalEntry = _arriveLists.remove(oid);
|
||||
|
||||
try {
|
||||
// make sure we have a place object still
|
||||
if (_scObj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if we were going to remove this sprite, do it now
|
||||
if (null != _pendingRemoveSprites.remove(oid)) {
|
||||
removeSprite(sprite);
|
||||
return;
|
||||
}
|
||||
|
||||
// look up the location occupied by the user in question
|
||||
var loc :SceneLocation = locationForBody(oid);
|
||||
if (loc == null) {
|
||||
log.warning("Sprite completed path but no location found?",
|
||||
"oid", oid, "sprite", sprite, "occlocs", _scObj.occupantLocs);
|
||||
return;
|
||||
}
|
||||
|
||||
handleLocationArrived(sprite, loc);
|
||||
|
||||
// notify any arrival listener
|
||||
if (alist != null && loc.loc.equals(alist.loc)) {
|
||||
alist.listener(sprite, loc.loc);
|
||||
}
|
||||
|
||||
} finally {
|
||||
// keep track of the last time we came to rest
|
||||
if (sprite == _selfSprite) {
|
||||
centerView(false, true);
|
||||
_centerStamp = tickStamp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location id of the location at which the player with the specified body oid
|
||||
* resides.
|
||||
*/
|
||||
protected function locationForBody (bodyOid :int) :SceneLocation
|
||||
{
|
||||
return (_scObj == null) ? null :
|
||||
SceneLocation(_scObj.occupantLocs.get(bodyOid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a sprite has arrived at its location.
|
||||
*/
|
||||
protected function handleLocationArrived (sprite :CharacterIsoSprite, loc :SceneLocation) :void
|
||||
{
|
||||
// orient them properly
|
||||
sprite.placeAtLoc(StageLocation(loc.loc));
|
||||
|
||||
// if this is us, recompute our proximate sprite set
|
||||
if (sprite.getBodyOid() == myOid()) {
|
||||
recomputeProximate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a listener to be notified when the sprite associated with the specified body
|
||||
* arrives at the specified scene location. If the body is not currently on a path to that
|
||||
* location, the listener will be dropped. If the body arrives at any other location, the
|
||||
* request will be dropped. Only if the body completes their current path toward the specified
|
||||
* location will the listener be notified.
|
||||
*
|
||||
* @return true if the listener was added, false if there was no such sprite or they were not
|
||||
* moving.
|
||||
*/
|
||||
public function addArrivalListener (bodyOid :int, loc :Location, listener :Function) :Boolean
|
||||
{
|
||||
var sprite :CharacterIsoSprite = getSprite(bodyOid);
|
||||
if (sprite != null && sprite.isMoving()) {
|
||||
_arriveLists.put(bodyOid, new ArrivalEntry(loc, listener));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function occupantEntryUpdated (event :EntryUpdatedEvent) :void
|
||||
{
|
||||
if (event.getName() == SpotSceneObject.OCCUPANT_LOCS) {
|
||||
occupantMoved(SceneLocation(event.getOldEntry()),
|
||||
SceneLocation(event.getEntry()), true);
|
||||
}
|
||||
}
|
||||
|
||||
protected function pathCompleted (sprite :CharacterIsoSprite, path :Path, when :int) :void
|
||||
{
|
||||
handleSpriteArrived(sprite, when);
|
||||
}
|
||||
|
||||
protected var _occupantListener :SetListener = new SetAdapter(null, occupantEntryUpdated, null);
|
||||
|
||||
protected var _cCtx :CrowdContext;
|
||||
|
||||
/** Map bodyOid to all the sprites we're handling. */
|
||||
protected var _sprites :Map = Maps.newMapOf(int);
|
||||
|
||||
/** Map bodyOid to all the sprites we're getting ready to remove. */
|
||||
protected var _pendingRemoveSprites :Map = Maps.newMapOf(int);
|
||||
|
||||
/** Map bodyOid to listeners waiting for sprites to get somewhere. */
|
||||
protected var _arriveLists :Map = Maps.newMapOf(int);
|
||||
|
||||
/** Timestamp for last time we moved, used for auto-recentering. */
|
||||
protected var _centerStamp :int;
|
||||
|
||||
/** The sprite associated with our client. */
|
||||
protected var _selfSprite :CharacterIsoSprite;
|
||||
|
||||
/** The pixel radius around our sprite which we consider sufficiently
|
||||
* proximate that we keep sprites around for occupants therein. */
|
||||
protected var _proxrad :int = 100;
|
||||
|
||||
protected var _scObj :StageSceneObject;
|
||||
|
||||
/** Our sprite path velocity. */
|
||||
// if we had more frames, maybe we could only update their
|
||||
// location when their frame changed. Alas, we do not.
|
||||
protected static const SPRITE_PATH_VELOCITY :Number = 0.0025;
|
||||
}
|
||||
}
|
||||
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
|
||||
class ArrivalEntry
|
||||
{
|
||||
public var loc :Location;
|
||||
public var listener :Function;
|
||||
|
||||
public function ArrivalEntry (loc :Location, listener :Function)
|
||||
{
|
||||
this.loc = loc;
|
||||
this.listener = listener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import flash.display.Bitmap;
|
||||
import flash.display.DisplayObject;
|
||||
import flash.geom.Point;
|
||||
|
||||
import as3isolib.display.IsoSprite;
|
||||
|
||||
import com.threerings.miso.client.PriorityIsoDisplayObject;
|
||||
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
|
||||
public class PortalIsoSprite extends IsoSprite
|
||||
implements PriorityIsoDisplayObject
|
||||
{
|
||||
public function PortalIsoSprite (img :DisplayObject, x :int, y :int, portal :Portal)
|
||||
{
|
||||
sprites = [img];
|
||||
setSize(1, 1, 1);
|
||||
moveTo(x, y, 0);
|
||||
setRaised(false);
|
||||
_portal = portal;
|
||||
}
|
||||
|
||||
public function getPriority () :int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPortal () :Portal
|
||||
{
|
||||
return _portal;
|
||||
}
|
||||
|
||||
public function hitTest (stageX :int, stageY :int) :Boolean
|
||||
{
|
||||
if (sprites == null || sprites.length == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sprites[0] is Bitmap) {
|
||||
if (!sprites[0].hitTestPoint(stageX, stageY, true)) {
|
||||
// Doesn't even hit the bounds...
|
||||
return false;
|
||||
}
|
||||
// Check the actual pixels...
|
||||
var pt :Point = sprites[0].globalToLocal(new Point(stageX, stageY));
|
||||
return Bitmap(sprites[0]).bitmapData.hitTest(new Point(0, 0), 0, pt);
|
||||
} else {
|
||||
return sprites[0].hitTestPoint(stageX, stageY, true);
|
||||
}
|
||||
}
|
||||
|
||||
public function setRaised (raised :Boolean) :void
|
||||
{
|
||||
sprites[0].alpha = (raised ? 1.0 : 0.5);
|
||||
}
|
||||
|
||||
protected var _portal :Portal;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
import com.threerings.util.Maps;
|
||||
|
||||
import com.threerings.media.image.ClassRecord;
|
||||
import com.threerings.media.image.ColorPository;
|
||||
import com.threerings.media.image.ColorRecord;
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.tile.Colorizer;
|
||||
|
||||
import com.threerings.miso.data.ObjectInfo;
|
||||
|
||||
import com.threerings.stage.data.StageScene;
|
||||
|
||||
/**
|
||||
* Handles colorization of object tiles in a scene.
|
||||
*/
|
||||
public class SceneColorizer implements Colorizer
|
||||
{
|
||||
private var log :Log = Log.getLog(SceneColorizer);
|
||||
|
||||
/**
|
||||
* Creates a scene colorizer for the supplied scene.
|
||||
*/
|
||||
public function SceneColorizer (cpos :ColorPository, scene :StageScene)
|
||||
{
|
||||
_cpos = cpos;
|
||||
_scene = scene;
|
||||
|
||||
// enumerate the color ids for all possible colorization classes
|
||||
for each (var colClass :ClassRecord in _cpos.getClasses()) {
|
||||
_cids.put(colClass.name, _cpos.getColorIds(colClass.name));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an auxiliary colorizer that overrides our colorizations.
|
||||
*/
|
||||
public function setAuxiliary (aux :Colorizer) :void
|
||||
{
|
||||
_aux = aux;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a colorizer for the supplied scene object.
|
||||
*/
|
||||
public function getColorizer (oinfo :ObjectInfo) :Colorizer
|
||||
{
|
||||
// if the object has no custom colorizations, return the default
|
||||
// colorizer
|
||||
if (oinfo.zations == 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
// otherwise create a custom colorizer that returns this object's
|
||||
// custom colorization assignments
|
||||
return new BaseColorizer(oinfo, this, _cpos);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Colorizer
|
||||
public function getColorization (index :int, zation :String) :Colorization
|
||||
{
|
||||
// This method is called when an object in the scene has no colorization
|
||||
// of its own defined for a particular color class.
|
||||
if (_aux != null) {
|
||||
var c :Colorization = _aux.getColorization(index, zation);
|
||||
if (c != null) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return _cpos.getColorizationByNameAndId(zation, getColorId(zation));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the colorId to use for the specified colorization.
|
||||
*/
|
||||
public function getColorId (zation :String) :int
|
||||
{
|
||||
// 1. We see if the scene contains a default color we should use.
|
||||
var rec :ClassRecord = _cpos.getClassRecordByName(zation);
|
||||
var colorId :int = _scene.getDefaultColor(rec.classId);
|
||||
if (colorId == -1) {
|
||||
// 2. If the scene does not contain a color, see if a default
|
||||
// is defined for that color class.
|
||||
var def :ColorRecord = rec.getDefault();
|
||||
if (def != null) {
|
||||
return def.colorId;
|
||||
}
|
||||
|
||||
// 3. If there are no defaults whatsoever, just hash on the zoneId.
|
||||
var cids :Array= _cids.get(zation);
|
||||
if (cids == null) {
|
||||
log.warning("Zoiks, have no colorizations for '" + zation + "'.");
|
||||
return -1;
|
||||
} else {
|
||||
colorId = cids[_scene.getZoneId() % cids.length];
|
||||
}
|
||||
}
|
||||
return colorId;
|
||||
}
|
||||
|
||||
/** An auxiliary colorizer which may temporarily return
|
||||
* non-standard colorizations. */
|
||||
protected var _aux :Colorizer;
|
||||
|
||||
/** The entity from which we obtain colorization info. */
|
||||
protected var _cpos :ColorPository;
|
||||
|
||||
/** The scene for which we're providing zations. */
|
||||
protected var _scene :StageScene;
|
||||
|
||||
/** Contains our colorization class information. */
|
||||
protected var _cids :Map = Maps.newMapOf(String);
|
||||
}
|
||||
}
|
||||
|
||||
import com.threerings.media.image.ColorPository;
|
||||
import com.threerings.media.image.Colorization;
|
||||
import com.threerings.media.tile.Colorizer;
|
||||
|
||||
import com.threerings.miso.data.ObjectInfo;
|
||||
|
||||
import com.threerings.stage.client.SceneColorizer;
|
||||
|
||||
class BaseColorizer implements Colorizer {
|
||||
public function BaseColorizer (oInfo :ObjectInfo, defColorizer :SceneColorizer,
|
||||
cpos :ColorPository)
|
||||
{
|
||||
_oInfo = oInfo;
|
||||
_defColorizer = defColorizer;
|
||||
_cpos = cpos;
|
||||
}
|
||||
|
||||
public function getColorization (index :int, zation :String) :Colorization {
|
||||
var colorId :int = 0;
|
||||
switch (index) {
|
||||
case 0: colorId = _oInfo.getPrimaryZation(); break;
|
||||
case 1: colorId = _oInfo.getSecondaryZation(); break;
|
||||
case 2: colorId = _oInfo.getTertiaryZation(); break;
|
||||
case 3: colorId = _oInfo.getQuaternaryZation(); break;
|
||||
}
|
||||
|
||||
if (colorId == 0) {
|
||||
return _defColorizer.getColorization(index, zation);
|
||||
} else {
|
||||
return _cpos.getColorizationByNameAndId(zation, colorId);
|
||||
}
|
||||
}
|
||||
|
||||
protected var _oInfo :ObjectInfo;
|
||||
protected var _defColorizer :SceneColorizer;
|
||||
protected var _cpos :ColorPository;
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
|
||||
import as3isolib.display.IsoSprite;
|
||||
import as3isolib.display.IsoView;
|
||||
import as3isolib.display.scene.IsoScene;
|
||||
|
||||
import com.threerings.util.Iterator;
|
||||
|
||||
import com.threerings.miso.client.MisoScenePanel;
|
||||
import com.threerings.miso.client.SceneBlock;
|
||||
import com.threerings.miso.data.MisoSceneModel;
|
||||
import com.threerings.miso.util.MisoContext;
|
||||
import com.threerings.miso.util.MisoSceneMetrics;
|
||||
import com.threerings.miso.util.MisoUtil;
|
||||
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
import com.threerings.whirled.spot.data.SpotScene;
|
||||
|
||||
import com.threerings.stage.data.StageLocation;
|
||||
|
||||
public class StageSceneBlock extends SceneBlock
|
||||
{
|
||||
public function StageSceneBlock (key :int, objScene :IsoScene, portalScene :IsoScene,
|
||||
isoView :IsoView, metrics :MisoSceneMetrics, spotScene :SpotScene)
|
||||
{
|
||||
super(key, objScene, isoView, metrics);
|
||||
_spotScene = spotScene;
|
||||
_portalScene = portalScene;
|
||||
}
|
||||
|
||||
override public function resolve (ctx :MisoContext, model :MisoSceneModel,
|
||||
panel :MisoScenePanel, completeCallback :Function) :void
|
||||
{
|
||||
_tryingPortals = true;
|
||||
super.resolve(ctx, model, panel, completeCallback);
|
||||
|
||||
var bx :int = getBlockX(_key);
|
||||
var by :int = getBlockY(_key);
|
||||
var iter :Iterator = _spotScene.getPortals();
|
||||
while (iter.hasNext()) {
|
||||
var portal :Portal = Portal(iter.next());
|
||||
var x :int = MisoUtil.fullToTile(StageLocation(portal.loc).x);
|
||||
var y :int = MisoUtil.fullToTile(StageLocation(portal.loc).y);
|
||||
if (x < bx || x >= bx + BLOCK_SIZE || y < by || y >= by + BLOCK_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var fineX :int = MisoUtil.fullToFine(StageLocation(portal.loc).x);
|
||||
var fineY :int = MisoUtil.fullToFine(StageLocation(portal.loc).y);
|
||||
|
||||
// Grab the portal image, and center it.
|
||||
var img :DisplayObject =
|
||||
StageScenePanel(panel).getPortalImage(StageLocation(portal.loc).orient);
|
||||
img.x = -img.width/2 + int(_metrics.finehwid * (fineX - fineY));
|
||||
img.y = -img.height/2 + int(_metrics.finehhei * (fineX + fineY));
|
||||
var portalSprite :PortalIsoSprite = new PortalIsoSprite(img, x, y, portal);
|
||||
|
||||
if (_portSprites == null) {
|
||||
_portSprites = [];
|
||||
}
|
||||
_portSprites.push(portalSprite);
|
||||
}
|
||||
|
||||
_tryingPortals = false;
|
||||
maybeLoaded();
|
||||
}
|
||||
|
||||
override public function render () :void
|
||||
{
|
||||
super.render();
|
||||
for each (var sprite :IsoSprite in _portSprites) {
|
||||
_portalScene.addChild(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
override public function release () :void
|
||||
{
|
||||
super.release();
|
||||
for each (var sprite :IsoSprite in _portSprites) {
|
||||
_portalScene.removeChild(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
override protected function maybeLoaded () :void
|
||||
{
|
||||
// If we're still working on getting our portals setup, skip it...
|
||||
if (!_tryingPortals) {
|
||||
super.maybeLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
protected var _spotScene :SpotScene;
|
||||
|
||||
protected var _tryingPortals :Boolean;
|
||||
|
||||
protected var _portalScene :IsoScene;
|
||||
|
||||
protected var _portSprites :Array;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
|
||||
import com.threerings.crowd.client.PlaceView;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.miso.util.MisoSceneMetrics;
|
||||
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.spot.client.SpotSceneController;
|
||||
|
||||
import com.threerings.stage.data.StageLocation;
|
||||
import com.threerings.stage.util.StageContext;
|
||||
|
||||
public class StageSceneController extends SpotSceneController
|
||||
{
|
||||
public var log :Log = Log.getLog(StageSceneController);
|
||||
|
||||
/**
|
||||
* Called when the user clicks on a location within the scene.
|
||||
*/
|
||||
public function handleLocationClicked (source :Object, loc :StageLocation) :void
|
||||
{
|
||||
log.warning("handleLocationClicked(" + source + ", " + loc + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a cluster clicked event.
|
||||
*
|
||||
* @param tuple the cluster that was clicked and the screen coords of the click.
|
||||
*/
|
||||
public function handleClusterClicked (source :Object, clusterClick :ClusterClickedInfo) :void
|
||||
{
|
||||
log.warning("handleClusterClicked(" + source + ", " + clusterClick + ")");
|
||||
}
|
||||
|
||||
override protected function createPlaceView (ctx :CrowdContext) :PlaceView
|
||||
{
|
||||
return new StageScenePanel(StageContext(ctx), this, new MisoSceneMetrics());
|
||||
}
|
||||
|
||||
override protected function sceneUpdated (update :SceneUpdate) :void
|
||||
{
|
||||
super.sceneUpdated(update);
|
||||
|
||||
// let the scene panel know to rethink everything
|
||||
(StageScenePanel(_view)).sceneUpdated(update);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,189 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import flash.display.DisplayObject;
|
||||
|
||||
import as3isolib.display.IsoSprite;
|
||||
import as3isolib.display.scene.IsoScene;
|
||||
|
||||
import com.threerings.util.Controller;
|
||||
import com.threerings.util.Log;
|
||||
|
||||
import com.threerings.media.tile.Colorizer;
|
||||
|
||||
import com.threerings.miso.client.MisoScenePanel;
|
||||
import com.threerings.miso.client.PriorityIsoDisplayObject;
|
||||
import com.threerings.miso.client.SceneBlock;
|
||||
import com.threerings.miso.data.ObjectInfo;
|
||||
import com.threerings.miso.util.MisoSceneMetrics;
|
||||
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
|
||||
import com.threerings.stage.data.StageMisoSceneModel;
|
||||
import com.threerings.stage.data.StageScene;
|
||||
import com.threerings.stage.util.StageContext;
|
||||
|
||||
/**
|
||||
* Eventually responsible for rendering a stage scene - but for now it's a stub.
|
||||
*/
|
||||
public class StageScenePanel extends MisoScenePanel
|
||||
{
|
||||
private var log :Log = Log.getLog(StageScenePanel);
|
||||
|
||||
public function StageScenePanel (ctx :StageContext, ctrl :Controller, metrics :MisoSceneMetrics)
|
||||
{
|
||||
super(ctx, metrics);
|
||||
_sCtx = ctx;
|
||||
}
|
||||
|
||||
public function setScene (scene :StageScene) :void
|
||||
{
|
||||
_scene = scene;
|
||||
if (_scene != null) {
|
||||
_rizer = new SceneColorizer(_sCtx.getColorPository(), _scene);
|
||||
recomputePortals();
|
||||
setSceneModel(StageMisoSceneModel.getSceneModel(scene.getSceneModel()));
|
||||
} else {
|
||||
log.warning("Zoiks! We can't display a null scene!");
|
||||
// TODO: display something to the user letting them know that
|
||||
// we're so hosed that we don't even know what time it is
|
||||
}
|
||||
}
|
||||
|
||||
public function recomputePortals () :void
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
override protected function computeOverHover (mx :int, my :int) :Object
|
||||
{
|
||||
var hits :Array =
|
||||
_overPortalScene.displayListChildren.filter(
|
||||
function(val :Object, idx :int, arr :Array) :Boolean {
|
||||
if (val is PriorityIsoDisplayObject) {
|
||||
return PriorityIsoDisplayObject(val).hitTest(mx, my);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (hits.length > 0) {
|
||||
return hits[0];
|
||||
} else {
|
||||
hits = _portalScene.displayListChildren.filter(
|
||||
function(val :Object, idx :int, arr :Array) :Boolean {
|
||||
if (val is PriorityIsoDisplayObject) {
|
||||
return PriorityIsoDisplayObject(val).hitTest(mx, my);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (hits.length > 0) {
|
||||
return hits[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override protected function hoverObjectChanged (oldHover :Object, newHover :Object) :void
|
||||
{
|
||||
super.hoverObjectChanged(oldHover, newHover);
|
||||
|
||||
if (oldHover is PortalIsoSprite) {
|
||||
var oldPortal :PortalIsoSprite = PortalIsoSprite(oldHover);
|
||||
oldPortal.setRaised(false);
|
||||
|
||||
if (_overPortalScene.removeChild(oldPortal) != null) {
|
||||
_portalScene.addChild(oldPortal);
|
||||
}
|
||||
|
||||
_portalScene.render();
|
||||
_overPortalScene.render();
|
||||
}
|
||||
|
||||
if (newHover is PortalIsoSprite) {
|
||||
var newPortal :PortalIsoSprite = PortalIsoSprite(newHover);
|
||||
newPortal.setRaised(true);
|
||||
|
||||
if (_portalScene.removeChild(newPortal) != null) {
|
||||
_overPortalScene.addChild(newPortal);
|
||||
}
|
||||
|
||||
_portalScene.render();
|
||||
_overPortalScene.render();
|
||||
}
|
||||
}
|
||||
|
||||
override protected function renderObjectScenes () :void
|
||||
{
|
||||
super.renderObjectScenes();
|
||||
_portalScene.render();
|
||||
_overPortalScene.render();
|
||||
}
|
||||
|
||||
override protected function addObjectScenes () :void
|
||||
{
|
||||
_portalScene = new IsoScene();
|
||||
_isoView.addScene(_portalScene);
|
||||
super.addObjectScenes();
|
||||
_overPortalScene = new IsoScene();
|
||||
_isoView.addScene(_overPortalScene);
|
||||
}
|
||||
|
||||
override protected function createSceneBlock (blockKey :int) :SceneBlock
|
||||
{
|
||||
return new StageSceneBlock(blockKey, _objScene, _portalScene, _isoView, _metrics,
|
||||
_scene);
|
||||
}
|
||||
|
||||
public function sceneUpdated (update :SceneUpdate) :void
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public function getPortalImage (dir :int) :DisplayObject
|
||||
{
|
||||
throw new Error("abstract");
|
||||
}
|
||||
|
||||
override public function getColorizer (oinfo :ObjectInfo) :Colorizer
|
||||
{
|
||||
return _rizer.getColorizer(oinfo);
|
||||
}
|
||||
|
||||
|
||||
protected var _portalScene :IsoScene;
|
||||
protected var _overPortalScene :IsoScene;
|
||||
|
||||
/** The scene we're presenting in our panel. */
|
||||
protected var _scene :StageScene;
|
||||
|
||||
/** Used to recolor any tiles in our scene. */
|
||||
protected var _rizer :SceneColorizer;
|
||||
|
||||
/** Our appropriately-cast stage client context. */
|
||||
protected var _sCtx :StageContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
|
||||
import com.threerings.miso.data.ObjectInfo;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java StageSceneService interface.
|
||||
*/
|
||||
public interface StageSceneService extends InvocationService
|
||||
{
|
||||
// from Java interface StageSceneService
|
||||
function addObject (arg1 :ObjectInfo, arg2 :InvocationService_ConfirmListener) :void;
|
||||
|
||||
// from Java interface StageSceneService
|
||||
function removeObjects (arg1 :TypedArray /* of class com.threerings.miso.data.ObjectInfo */, arg2 :InvocationService_ConfirmListener) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
|
||||
/**
|
||||
* Update to change the default colorization for objects in a scene which
|
||||
* do not define their own colorization.
|
||||
*/
|
||||
public class DefaultColorUpdate extends SceneUpdate
|
||||
{
|
||||
/** The class id of the colorization we're changing. */
|
||||
public var classId :int;
|
||||
|
||||
/** The color id to set as the new default, or -1 to remove the default. */
|
||||
public var colorId :int;
|
||||
|
||||
/**
|
||||
* Initializes this update.
|
||||
*/
|
||||
public function initUpdate (targetId :int, targetVersion :int,
|
||||
classId :int, colorId :int) :void
|
||||
{
|
||||
init(targetId, targetVersion);
|
||||
this.classId = classId;
|
||||
this.colorId = colorId;
|
||||
}
|
||||
|
||||
override public function apply (model :SceneModel) :void
|
||||
{
|
||||
super.apply(model);
|
||||
|
||||
var smodel :StageSceneModel = StageSceneModel(model);
|
||||
smodel.setDefaultColor(classId, colorId);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
classId = ins.readInt();
|
||||
colorId = ins.readInt();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(classId);
|
||||
out.writeInt(colorId);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.miso.data.ObjectInfo;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
|
||||
/**
|
||||
* A scene update that is broadcast when objects have been added to or removed
|
||||
* from the scene.
|
||||
*/
|
||||
public class ModifyObjectsUpdate extends SceneUpdate
|
||||
{
|
||||
/** The objects added to the scene (or <code>null</code> for none). */
|
||||
public var added :TypedArray;
|
||||
|
||||
/** The objects removed from the scene (or <code>null</code> for none). */
|
||||
public var removed :TypedArray;
|
||||
|
||||
/**
|
||||
* Initializes this update with all necessary data.
|
||||
*
|
||||
* @param added the objects added to the scene, or <code>null</code> for
|
||||
* none
|
||||
* @param removed the objects removed from the scene, or <code>null</code>
|
||||
* for none
|
||||
*/
|
||||
public function initUpdate (targetId :int, targetVersion :int, added :Array,
|
||||
removed :Array) :void
|
||||
{
|
||||
init(targetId, targetVersion);
|
||||
this.added = TypedArray.create(ObjectInfo, added);
|
||||
this.removed = TypedArray.create(ObjectInfo, removed);
|
||||
}
|
||||
|
||||
override public function apply (model :SceneModel) :void
|
||||
{
|
||||
super.apply(model);
|
||||
|
||||
var mmodel :StageMisoSceneModel = StageMisoSceneModel.getSceneModel(model);
|
||||
|
||||
// wipe out the objects that need to go
|
||||
if (removed != null) {
|
||||
for each (var rmElement :ObjectInfo in removed) {
|
||||
mmodel.removeObject(rmElement);
|
||||
}
|
||||
}
|
||||
|
||||
// add the new objects
|
||||
if (added != null) {
|
||||
for each (var addElement :ObjectInfo in added) {
|
||||
mmodel.addObject(addElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
added = ins.readObject(TypedArray);
|
||||
removed = ins.readObject(TypedArray);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(added);
|
||||
out.writeObject(removed);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.DirectionCodes;
|
||||
import com.threerings.util.DirectionUtil;
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
|
||||
import com.threerings.stage.data.StageLocation;
|
||||
|
||||
/**
|
||||
* Contains information on a scene occupant's position and orientation.
|
||||
*/
|
||||
public class StageLocation extends SimpleStreamableObject
|
||||
implements Location, Hashable
|
||||
{
|
||||
/** The user's x position (interpreted by the display system). */
|
||||
public var x :int;
|
||||
|
||||
/** The user's y position (interpreted by the display system). */
|
||||
public var y :int;
|
||||
|
||||
/** The user's orientation (defined by {@link DirectionCodes}). */
|
||||
public var orient :int;
|
||||
|
||||
public function StageLocation (x :int = 0, y :int = 0, orient :int = 0)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.orient = orient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a reasonable hashcode for location instances.
|
||||
*/
|
||||
|
||||
public function hashCode () :int
|
||||
{
|
||||
return x ^ y;
|
||||
}
|
||||
|
||||
public function clone () :Object
|
||||
{
|
||||
var newLoc :StageLocation = (ClassUtil.newInstance(this) as StageLocation);
|
||||
newLoc.x = x;
|
||||
newLoc.y = y;
|
||||
newLoc.orient = orient;
|
||||
return newLoc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location equality is determined by coordinates.
|
||||
*/
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
if (other is StageLocation) {
|
||||
var that :StageLocation = StageLocation(other);
|
||||
return (this.x == that.x) && (this.y == that.y);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@link Object#toString} helper function. */
|
||||
public function orientToString () :String
|
||||
{
|
||||
return DirectionUtil.toShortString(orient);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Location
|
||||
public function getOpposite () :Location
|
||||
{
|
||||
var opp :StageLocation = StageLocation(clone());
|
||||
opp.orient = DirectionUtil.getOpposite(orient);
|
||||
return opp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location equivalence means that the coordinates and orientation are
|
||||
* the same.
|
||||
*/
|
||||
public function equivalent (oloc :Location) :Boolean
|
||||
{
|
||||
return equals(oloc) && (orient == (StageLocation(oloc)).orient);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
x = ins.readInt();
|
||||
y = ins.readInt();
|
||||
orient = ins.readByte();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(x);
|
||||
out.writeInt(y);
|
||||
out.writeByte(orient);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.miso.data.SparseMisoSceneModel;
|
||||
import com.threerings.miso.data.SparseMisoSceneModel_Section;
|
||||
|
||||
import com.threerings.whirled.data.AuxModel;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
import com.threerings.stage.data.StageMisoSceneModel;
|
||||
|
||||
/**
|
||||
* Extends the {@link SparseMisoSceneModel} with the necessary interface
|
||||
* to wire it up to the Whirled auxiliary model system.
|
||||
*/
|
||||
public class StageMisoSceneModel extends SparseMisoSceneModel
|
||||
implements AuxModel
|
||||
{
|
||||
/** The width (in tiles) of a scene section. */
|
||||
public static const SECTION_WIDTH :int = 9;
|
||||
|
||||
/** The height (in tiles) of a scene section. */
|
||||
public static const SECTION_HEIGHT :int = 9;
|
||||
|
||||
/**
|
||||
* Locates and returns the {@link StageMisoSceneModel} among the
|
||||
* auxiliary scene models associated with the supplied scene model.
|
||||
* <code>null</code> is returned if no miso scene model could be
|
||||
* found.
|
||||
*/
|
||||
public static function getSceneModel (model :SceneModel) :StageMisoSceneModel
|
||||
{
|
||||
for each (var auxModel :AuxModel in model.auxModels) {
|
||||
if (auxModel is StageMisoSceneModel) {
|
||||
return StageMisoSceneModel(auxModel);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
override public function clone () :Object
|
||||
{
|
||||
return StageMisoSceneModel(super.clone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the section identified by the specified key, or null if no
|
||||
* section exists for that key.
|
||||
*/
|
||||
public function getSectionByKey (key :int) :SparseMisoSceneModel_Section
|
||||
{
|
||||
return _sections.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the section key for the specified tile coordinate.
|
||||
*/
|
||||
public function getSectionKey (x :int, y :int) :Integer
|
||||
{
|
||||
return key(x, y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.crowd.data.OccupantInfo;
|
||||
|
||||
/**
|
||||
* Extends the standard occupant info with stage specific business.
|
||||
*/
|
||||
public class StageOccupantInfo extends OccupantInfo
|
||||
{
|
||||
/**
|
||||
* Should return true if the occupant in question is available to be
|
||||
* clustered with, false if they are "busy". This means that a user
|
||||
* can click on them and start a chat circle.
|
||||
*/
|
||||
public function isClusterable () :Boolean
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.util.Iterator;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneImpl;
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
import com.threerings.whirled.spot.data.SpotScene;
|
||||
import com.threerings.whirled.spot.data.SpotSceneImpl;
|
||||
import com.threerings.whirled.spot.data.SpotSceneModel;
|
||||
|
||||
public class StageScene extends SceneImpl
|
||||
implements SpotScene
|
||||
{
|
||||
public function StageScene (model :StageSceneModel, config :PlaceConfig)
|
||||
{
|
||||
super(model, config);
|
||||
_ssModel = model;
|
||||
_sdelegate = new SpotSceneImpl(SpotSceneModel.getSceneModel(_model));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default color id to use for the specified colorization class,
|
||||
* or -1 if no default is set.
|
||||
*/
|
||||
public function getDefaultColor (classId :int) :int
|
||||
{
|
||||
return _ssModel.getDefaultColor(classId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default color to use for the specified colorization class id.
|
||||
* Setting the colorId to -1 disables the default.
|
||||
*/
|
||||
public function setDefaultColor (classId :int, colorId :int) :void
|
||||
{
|
||||
_ssModel.setDefaultColor(classId, colorId);
|
||||
}
|
||||
|
||||
public function getZoneId () :int
|
||||
{
|
||||
return _ssModel.zoneId;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getPortal (portalId :int) :Portal
|
||||
{
|
||||
return _sdelegate.getPortal(portalId);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getPortalCount () :int
|
||||
{
|
||||
return _sdelegate.getPortalCount();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getPortals () :Iterator
|
||||
{
|
||||
return _sdelegate.getPortals();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getNextPortalId () :int
|
||||
{
|
||||
return _sdelegate.getNextPortalId();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getDefaultEntrance () :Portal
|
||||
{
|
||||
return _sdelegate.getDefaultEntrance();
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function addPortal (portal :Portal) :void
|
||||
{
|
||||
_sdelegate.addPortal(portal);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function removePortal (portal :Portal) :void
|
||||
{
|
||||
_sdelegate.removePortal(portal);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setDefaultEntrance (portal :Portal) :void
|
||||
{
|
||||
_sdelegate.setDefaultEntrance(portal);
|
||||
}
|
||||
|
||||
protected var _ssModel :StageSceneModel;
|
||||
|
||||
/** Our spot scene delegate. */
|
||||
protected var _sdelegate :SpotSceneImpl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.stage.client.StageSceneController;
|
||||
|
||||
/**
|
||||
* Place configuration for the main isometric scenes in Stage.
|
||||
*/
|
||||
public class StageSceneConfig extends PlaceConfig
|
||||
{
|
||||
override public function createController () :PlaceController
|
||||
{
|
||||
return new StageSceneController();
|
||||
}
|
||||
|
||||
override public function getManagerClassName () :String
|
||||
{
|
||||
return "com.threerings.stage.server.StageSceneManager";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ConfirmMarshaller;
|
||||
|
||||
import com.threerings.miso.data.ObjectInfo;
|
||||
|
||||
import com.threerings.stage.client.StageSceneService;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>StageSceneService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class StageSceneMarshaller extends InvocationMarshaller
|
||||
implements StageSceneService
|
||||
{
|
||||
/** The method id used to dispatch <code>addObject</code> requests. */
|
||||
public static const ADD_OBJECT :int = 1;
|
||||
|
||||
// from interface StageSceneService
|
||||
public function addObject (arg1 :ObjectInfo, arg2 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(ADD_OBJECT, [
|
||||
arg1, listener2
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>removeObjects</code> requests. */
|
||||
public static const REMOVE_OBJECTS :int = 2;
|
||||
|
||||
// from interface StageSceneService
|
||||
public function removeObjects (arg1 :TypedArray /* of class com.threerings.miso.data.ObjectInfo */, arg2 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(REMOVE_OBJECTS, [
|
||||
arg1, listener2
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
import com.threerings.util.StreamableHashMap;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.spot.data.SpotSceneModel;
|
||||
|
||||
import com.threerings.stage.data.StageSceneModel;
|
||||
|
||||
/**
|
||||
* Extends the basic scene model with the notion of a scene type and
|
||||
* incorporates the necessary auxiliary models used by the Stage system.
|
||||
*/
|
||||
public class StageSceneModel extends SceneModel
|
||||
{
|
||||
/** A scene type code. */
|
||||
public static const WORLD :String = "world";
|
||||
|
||||
/** This scene's type which is a string identifier used to later
|
||||
* construct a specific controller to handle this scene. */
|
||||
public var type :String;
|
||||
|
||||
/** The zone id to which this scene belongs. */
|
||||
public var zoneId :int;
|
||||
|
||||
/** If non-null, contains default colorizations to use for objects
|
||||
* that do not have colorizations defined. */
|
||||
public var defaultColors :StreamableHashMap;
|
||||
|
||||
/**
|
||||
* Creates and returns a blank scene model.
|
||||
*/
|
||||
public static function blankStageSceneModel () :StageSceneModel
|
||||
{
|
||||
var model :StageSceneModel = new StageSceneModel();
|
||||
populateBlankStageSceneModel(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default colorId to use for a specified colorization
|
||||
* classId, or -1 to clear the default for that colorization.
|
||||
*/
|
||||
public function setDefaultColor (classId :int, colorId :int) :void
|
||||
{
|
||||
if (colorId == -1) {
|
||||
if (defaultColors != null) {
|
||||
defaultColors.remove(classId);
|
||||
if (defaultColors.size() == 0) {
|
||||
defaultColors = null;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (defaultColors == null) {
|
||||
defaultColors = new StreamableHashMap();
|
||||
}
|
||||
defaultColors.put(classId, colorId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default color to use for the specified colorization
|
||||
* classId, or -1 if no default is set for that colorization.
|
||||
*/
|
||||
public function getDefaultColor (classId :int) :int
|
||||
{
|
||||
if (defaultColors != null) {
|
||||
return defaultColors.get(new Integer(classId));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
type = ins.readField(String);
|
||||
zoneId = ins.readInt();
|
||||
defaultColors = ins.readObject(StreamableHashMap);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeField(type);
|
||||
out.writeInt(zoneId);
|
||||
out.writeObject(defaultColors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a blank scene model with blank values.
|
||||
*/
|
||||
protected static function populateBlankStageSceneModel (model :StageSceneModel) :void
|
||||
{
|
||||
populateBlankSceneModel(model);
|
||||
model.addAuxModel(new SpotSceneModel());
|
||||
model.addAuxModel(new StageMisoSceneModel());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
|
||||
import com.threerings.whirled.spot.data.SpotSceneObject;
|
||||
|
||||
public class StageSceneObject extends SpotSceneObject
|
||||
{
|
||||
// AUTO-GENERATED: FIELDS START
|
||||
/** The field name of the <code>stageSceneService</code> field. */
|
||||
public static const STAGE_SCENE_SERVICE :String = "stageSceneService";
|
||||
|
||||
/** The field name of the <code>lightLevel</code> field. */
|
||||
public static const LIGHT_LEVEL :String = "lightLevel";
|
||||
|
||||
/** The field name of the <code>lightShade</code> field. */
|
||||
public static const LIGHT_SHADE :String = "lightShade";
|
||||
// AUTO-GENERATED: FIELDS END
|
||||
|
||||
/** Provides stage scene services. */
|
||||
public var stageSceneService :StageSceneMarshaller;
|
||||
|
||||
/** The light level in this scene. 0f being fully on, 1f fully shaded. */
|
||||
public var lightLevel :Number = 0;
|
||||
|
||||
/** The color of the light. */
|
||||
public var lightShade :int = 0xFFFFFF;
|
||||
|
||||
// // AUTO-GENERATED: METHODS START
|
||||
// /**
|
||||
// * Requests that the <code>stageSceneService</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// @Generated(value={"com.threerings.presents.tools.GenDObjectTask"})
|
||||
// public void setStageSceneService (StageSceneMarshaller value)
|
||||
// {
|
||||
// StageSceneMarshaller ovalue = this.stageSceneService;
|
||||
// requestAttributeChange(
|
||||
// STAGE_SCENE_SERVICE, value, ovalue);
|
||||
// this.stageSceneService = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>lightLevel</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// @Generated(value={"com.threerings.presents.tools.GenDObjectTask"})
|
||||
// public void setLightLevel (float value)
|
||||
// {
|
||||
// float ovalue = this.lightLevel;
|
||||
// requestAttributeChange(
|
||||
// LIGHT_LEVEL, Float.valueOf(value), Float.valueOf(ovalue));
|
||||
// this.lightLevel = value;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that the <code>lightShade</code> field be set to the
|
||||
// * specified value. The local value will be updated immediately and an
|
||||
// * event will be propagated through the system to notify all listeners
|
||||
// * that the attribute did change. Proxied copies of this object (on
|
||||
// * clients) will apply the value change when they received the
|
||||
// * attribute changed notification.
|
||||
// */
|
||||
// @Generated(value={"com.threerings.presents.tools.GenDObjectTask"})
|
||||
// public void setLightShade (int value)
|
||||
// {
|
||||
// int ovalue = this.lightShade;
|
||||
// requestAttributeChange(
|
||||
// LIGHT_SHADE, Integer.valueOf(value), Integer.valueOf(ovalue));
|
||||
// this.lightShade = value;
|
||||
// }
|
||||
// // AUTO-GENERATED: METHODS END
|
||||
//
|
||||
// override public function writeObject (out :ObjectOutputStream) :void
|
||||
// {
|
||||
// super.writeObject(out);
|
||||
//
|
||||
// out.writeObject(stageSceneService);
|
||||
// out.writeFloat(lightLevel);
|
||||
// out.writeInt(lightShade);
|
||||
// }
|
||||
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
|
||||
stageSceneService = ins.readObject();
|
||||
lightLevel = ins.readFloat();
|
||||
lightShade = ins.readInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.stage.util {
|
||||
|
||||
import com.threerings.media.image.ColorPository;
|
||||
|
||||
import com.threerings.miso.util.MisoContext;
|
||||
|
||||
/**
|
||||
* A context that provides for the myriad requirements of the Stage system.
|
||||
* This is currently just a stub.
|
||||
*/
|
||||
public interface StageContext extends MisoContext
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the colorization repository.
|
||||
*/
|
||||
function getColorPository () :ColorPository;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* Contains information on a pending scene change.
|
||||
*/
|
||||
public class PendingData
|
||||
{
|
||||
/** The id of the scene to which we are moving. */
|
||||
public var sceneId :int;
|
||||
|
||||
/** The cached scene model for the scene to which wer'e moving, or null. */
|
||||
public var model :SceneModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import com.threerings.presents.dobj.MessageAdapter;
|
||||
import com.threerings.presents.dobj.MessageEvent;
|
||||
import com.threerings.presents.dobj.MessageListener;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.util.CrowdContext;
|
||||
|
||||
import com.threerings.whirled.data.SceneCodes;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
|
||||
/**
|
||||
* The base scene controller class. It is expected that users of the
|
||||
* Whirled services will extend this controller class when creating
|
||||
* specialized controllers for their scenes.
|
||||
*/
|
||||
public /*abstract*/ class SceneController extends PlaceController
|
||||
{
|
||||
// documentation inherited
|
||||
override public function init (ctx :CrowdContext, config :PlaceConfig) :void
|
||||
{
|
||||
super.init(ctx, config);
|
||||
_wctx = WhirledContext(ctx);
|
||||
|
||||
_updateListener = new MessageAdapter(
|
||||
function (event :MessageEvent) :void {
|
||||
if (event.getName() == SceneCodes.SCENE_UPDATE) {
|
||||
sceneUpdated(event.getArgs()[0] as SceneUpdate);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function willEnterPlace (plobj :PlaceObject) :void
|
||||
{
|
||||
super.willEnterPlace(plobj);
|
||||
plobj.addListener(_updateListener);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function didLeavePlace (plobj :PlaceObject) :void
|
||||
{
|
||||
super.didLeavePlace(plobj);
|
||||
plobj.removeListener(_updateListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called if a scene update is recorded while we
|
||||
* currently occupy a scene. The default implementation will update
|
||||
* our local scene and scene model, but derived classes will likely
|
||||
* want to ensure that the update is properly displayed.
|
||||
*/
|
||||
protected function sceneUpdated (update :SceneUpdate) :void
|
||||
{
|
||||
// apply the update to the scene
|
||||
_wctx.getSceneDirector().updateReceived(update);
|
||||
}
|
||||
|
||||
/** Used to listen for scene updates. */
|
||||
protected var _updateListener :MessageListener;
|
||||
|
||||
protected var _wctx :WhirledContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
|
||||
import com.threerings.whirled.client.SceneReceiver;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link SceneReceiver} instance.
|
||||
*/
|
||||
public class SceneDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static const RECEIVER_CODE :String =
|
||||
"c4d0cf66b81a6e83d119b2d607725651";
|
||||
|
||||
/** The method id used to dispatch {@link SceneReceiver#forcedMove}
|
||||
* notifications. */
|
||||
public static const FORCED_MOVE :int = 1;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public function SceneDecoder (receiver :SceneReceiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getReceiverCode () :String
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function dispatchNotification (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case FORCED_MOVE:
|
||||
(receiver as SceneReceiver).forcedMove(args[0] as int);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,656 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import flash.errors.IOError;
|
||||
import flash.errors.IllegalOperationError;
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.Map;
|
||||
import com.threerings.util.Maps;
|
||||
import com.threerings.util.ResultListener;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.ConfirmAdapter;
|
||||
import com.threerings.presents.data.InvocationCodes;
|
||||
|
||||
import com.threerings.crowd.client.LocationDirector;
|
||||
import com.threerings.crowd.client.LocationDirector_FailureHandler;
|
||||
import com.threerings.crowd.client.LocationObserver;
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.whirled.client.persist.SceneRepository;
|
||||
import com.threerings.whirled.data.Scene;
|
||||
import com.threerings.whirled.data.SceneCodes;
|
||||
import com.threerings.whirled.data.SceneMarshaller;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneObject;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
import com.threerings.whirled.util.NoSuchSceneError;
|
||||
import com.threerings.whirled.util.SceneFactory;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
|
||||
/**
|
||||
* The scene director is the client's interface to all things scene related. It interfaces with the
|
||||
* scene repository to ensure that scene objects are available when the client enters a particular
|
||||
* scene. It handles moving from scene to scene (it coordinates with the {@link LocationDirector}
|
||||
* in order to do this).
|
||||
*
|
||||
* <p> Note that when the scene director is in use instead of the location director, scene ids
|
||||
* instead of place oids will be supplied to {@link LocationObserver#locationMayChange} and {@link
|
||||
* LocationObserver#locationChangeFailed}.
|
||||
*/
|
||||
public class SceneDirector extends BasicDirector
|
||||
implements LocationDirector_FailureHandler, SceneReceiver, SceneService_SceneMoveListener,
|
||||
LocationObserver
|
||||
{
|
||||
private static const log :Log = Log.getLog(SceneDirector);
|
||||
|
||||
// statically reference classes we require
|
||||
SceneMarshaller;
|
||||
|
||||
/**
|
||||
* Creates a new scene director with the specified context.
|
||||
*
|
||||
* @param ctx the active client context.
|
||||
* @param locdir the location director in use on the client, with which the scene director will
|
||||
* coordinate when changing location.
|
||||
* @param screp the entity from which the scene director will load scene data from the local
|
||||
* client scene storage. This may be null when the SceneDirector is constructed, but it should
|
||||
* be supplied via {@link #setSceneRepository} prior to really using this director.
|
||||
* @param fact the factory that knows which derivation of {@link Scene} to create for the
|
||||
* current system.
|
||||
*/
|
||||
public function SceneDirector (ctx :WhirledContext, locdir :LocationDirector,
|
||||
screp :SceneRepository, fact :SceneFactory)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
// we'll need these for later
|
||||
_wctx = ctx;
|
||||
_locdir = locdir;
|
||||
setSceneRepository(screp);
|
||||
_fact = fact;
|
||||
|
||||
// we need to observe scene moves so that we can clear out if we change to a non-scene
|
||||
_locdir.addLocationObserver(this);
|
||||
|
||||
// set ourselves up as a failure handler with the location director because we need to do
|
||||
// special processing
|
||||
_locdir.setFailureHandler(this);
|
||||
|
||||
// register for scene notifications
|
||||
_wctx.getClient().getInvocationDirector().registerReceiver(new SceneDecoder(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the scene repository.
|
||||
*/
|
||||
public function setSceneRepository (screp :SceneRepository) :void
|
||||
{
|
||||
_screp = screp;
|
||||
_scache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display scene object associated with the scene we currently occupy or null if we
|
||||
* currently occupy no scene.
|
||||
*/
|
||||
public function getScene () :Scene
|
||||
{
|
||||
return _scene;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that this client move the specified scene. A request will be made and when the
|
||||
* response is received, the location observers will be notified of success or failure.
|
||||
*
|
||||
* @return true if the move to request was issued, false if it was rejected by a location
|
||||
* observer or because we have another request outstanding.
|
||||
*/
|
||||
public function moveTo (sceneId :int) :Boolean
|
||||
{
|
||||
// make sure the sceneId is valid
|
||||
if (sceneId < 0) {
|
||||
log.warning("Refusing moveTo(): invalid sceneId", "sceneId", sceneId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// sanity-check the destination scene id
|
||||
if (sceneId == _sceneId) {
|
||||
log.warning("Refusing request to move to the same scene", "sceneId", sceneId);
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare to move to this scene (sets up pending data)
|
||||
if (!prepareMoveTo(sceneId, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// do the deed
|
||||
sendMoveRequest();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares to move to the requested scene. The location observers are asked to ratify the move
|
||||
* and our pending scene mode is loaded from the scene repository. This can be called by
|
||||
* cooperating directors that need to coopt the moveTo process.
|
||||
*/
|
||||
public function prepareMoveTo (sceneId :int, rl :ResultListener) :Boolean
|
||||
{
|
||||
// first check to see if our observers are happy with this move request
|
||||
if (!_locdir.mayMoveTo(sceneId, rl)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// we need to call this both to mark that we're issuing a move request and to check to see
|
||||
// if the last issued request should be considered stale
|
||||
var refuse :Boolean = _locdir.checkRepeatMove();
|
||||
|
||||
// complain if we're over-writing a pending request
|
||||
if (movePending()) {
|
||||
if (refuse) {
|
||||
log.warning("Refusing moveTo; We have a request outstanding",
|
||||
"psid", _pendingData.sceneId, "nsid", sceneId);
|
||||
return false;
|
||||
|
||||
} else {
|
||||
log.warning("Overriding stale moveTo request",
|
||||
"psid", _pendingData.sceneId, "nsid", sceneId);
|
||||
}
|
||||
}
|
||||
|
||||
// create and initialize a new pending data record
|
||||
_pendingData = createPendingData();
|
||||
|
||||
// load up the cached pending scene so that we can communicate its version to the server
|
||||
_pendingData.model = loadSceneModel(sceneId);
|
||||
|
||||
// make a note of our pending scene id
|
||||
_pendingData.sceneId = sceneId;
|
||||
|
||||
// all systems go
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function that may be used to restore the scene director's pendingData to its
|
||||
* current state. This is primarily useful if you know something (such as a logoff) is about
|
||||
* to happen and you want to ensure you can restore the pending data after re-login.
|
||||
*/
|
||||
public function getPendingDataRestoreFunc () :Function
|
||||
{
|
||||
var pendingData :PendingData = _pendingData;
|
||||
|
||||
return function () :void {
|
||||
_pendingData = pendingData;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model loaded in preparation for a scene transition. This is made available only
|
||||
* for cooperating directors which may need to coopt the scene transition process. The pending
|
||||
* model is only valid immediately following a call to {@link #prepareMoveTo}.
|
||||
*/
|
||||
public function getPendingModel () :SceneModel
|
||||
{
|
||||
return _pendingData == null ? null : _pendingData.model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scene id set in preparation for a scene transition. As with
|
||||
* {@link #getPendingModel}, this is for cooperating directors.
|
||||
*/
|
||||
public function getPendingSceneId () :int
|
||||
{
|
||||
return _pendingData == null ? -1 : _pendingData.sceneId;
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveSucceeded (placeId :int, config :PlaceConfig) :void
|
||||
{
|
||||
// our move request was successful, deal with subscribing to our new place object
|
||||
_locdir.didMoveTo(placeId, config);
|
||||
|
||||
// keep track of our previous scene info
|
||||
_previousSceneId = _sceneId;
|
||||
|
||||
// clear out the old info
|
||||
clearScene();
|
||||
|
||||
// make the pending scene the active scene
|
||||
if (_pendingData == null) {
|
||||
log.warning("Aiya! Scene move succeeded but we have no pending data!",
|
||||
"prevId", _previousSceneId);
|
||||
return;
|
||||
}
|
||||
_sceneId = _pendingData.sceneId;
|
||||
_pendingData = null;
|
||||
|
||||
// since we're committed to moving to the new scene, we'll parallelize and go ahead and
|
||||
// load up the new scene now rather than wait until subscription to our place object
|
||||
// succeeds
|
||||
_model = loadSceneModel(_sceneId);
|
||||
|
||||
// complain if we didn't find a scene
|
||||
if (_model == null) {
|
||||
log.warning("Aiya! Unable to load scene", "sid", _sceneId, "plid", placeId);
|
||||
return;
|
||||
}
|
||||
|
||||
// and finally create a display scene instance with the model and the place config
|
||||
_scene = _fact.createScene(_model, config);
|
||||
|
||||
handlePendingForcedMove();
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveSucceededWithUpdates (
|
||||
placeId :int, config :PlaceConfig, updates :TypedArray) :void
|
||||
{
|
||||
log.info("Got updates", "placeId", placeId, "config", config, "updates", updates);
|
||||
|
||||
// apply the updates to our cached scene
|
||||
var model :SceneModel = loadSceneModel(_pendingData.sceneId);
|
||||
var failure :Boolean = false;
|
||||
for each (var update :SceneUpdate in updates) {
|
||||
try {
|
||||
update.validate(model);
|
||||
} catch (ise :IllegalOperationError) {
|
||||
log.warning("Scene update failed validation",
|
||||
"model", model, "update", update, "error", ise.message);
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
update.apply(model);
|
||||
} catch (e :Error) {
|
||||
log.warning("Failure applying scene update", "model", model, "update", update, e);
|
||||
failure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (failure) {
|
||||
// delete the now half-booched scene model from the repository
|
||||
try {
|
||||
_screp.deleteSceneModel(_pendingData.sceneId);
|
||||
} catch (ioe :IOError) {
|
||||
log.warning("Failure removing booched scene model",
|
||||
"sceneId", _pendingData.sceneId, ioe);
|
||||
}
|
||||
|
||||
// act as if the scene move failed, though we'll be in a funny state because the server
|
||||
// thinks we've changed scenes, but the client can try again without its booched scene
|
||||
// model
|
||||
requestFailed(InvocationCodes.INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
// store the updated scene in the repository
|
||||
persistSceneModel(model);
|
||||
|
||||
// finally pass through to the normal success handler
|
||||
moveSucceeded(placeId, config);
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveSucceededWithScene (
|
||||
placeId :int, config :PlaceConfig, model :SceneModel) :void
|
||||
{
|
||||
log.info("Got updated scene model",
|
||||
"placeId", placeId, "config", config,
|
||||
"scene", model.sceneId + "/" + model.name + "/" + model.version);
|
||||
|
||||
// update the model in the repository
|
||||
persistSceneModel(model);
|
||||
|
||||
// update our scene cache
|
||||
_scache.put(model.sceneId, model);
|
||||
|
||||
// and pass through to the normal move succeeded handler
|
||||
moveSucceeded(placeId, config);
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function moveRequiresServerSwitch (hostname :String, ports :TypedArray) :void
|
||||
{
|
||||
log.info("Scene switch requires server switch", "host", hostname, "ports", ports);
|
||||
// keep track of our current pending data because it will be cleared when we log off of
|
||||
// this server and onto the next one
|
||||
var pendingData :PendingData = _pendingData;
|
||||
// ship on over to the other server
|
||||
_wctx.getClient().moveToServer(hostname, ports, new ConfirmAdapter(
|
||||
function () :void { // succeeded
|
||||
// resend our move request now that we're connected to the new server
|
||||
_pendingData = pendingData;
|
||||
sendMoveRequest();
|
||||
}, requestFailed));
|
||||
}
|
||||
|
||||
// from interface SceneService_SceneMoveListener
|
||||
public function requestFailed (reason :String) :void
|
||||
{
|
||||
// clear out our pending info
|
||||
var sceneId :int = _pendingData.sceneId;
|
||||
_pendingData = null;
|
||||
|
||||
// let our observers know that something has gone horribly awry
|
||||
_locdir.failedToMoveTo(sceneId, reason);
|
||||
|
||||
handlePendingForcedMove();
|
||||
}
|
||||
|
||||
// from interface LocationObserver
|
||||
public function locationMayChange (placeId :int) :Boolean
|
||||
{
|
||||
return true; // fine with us
|
||||
}
|
||||
|
||||
// from interface LocationObserver
|
||||
public function locationDidChange (place :PlaceObject) :void
|
||||
{
|
||||
// if we're no longer in a scene, we need to clear out our scene information
|
||||
if (!(place is SceneObject)) {
|
||||
clearScene();
|
||||
}
|
||||
}
|
||||
|
||||
// from interface LocationObserver
|
||||
public function locationChangeFailed (placeId :int, reason :String) :void
|
||||
{
|
||||
// we don't care about this notification as we're registered as a LocationDirector
|
||||
// FailureHandler so we will later be requested to recover from our failed move
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by SceneController instances to tell us about an update to the current scene.
|
||||
*/
|
||||
public function updateReceived (update :SceneUpdate) :void
|
||||
{
|
||||
_scene.updateReceived(update);
|
||||
persistSceneModel(_scene.getSceneModel());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to clean up our place and scene state information when we leave a scene.
|
||||
*/
|
||||
public function didLeaveScene () :void
|
||||
{
|
||||
// let the location director know what's up
|
||||
_locdir.didLeavePlace();
|
||||
|
||||
// clear out our own scene state
|
||||
clearScene();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is a pending move request.
|
||||
*/
|
||||
public function movePending () :Boolean
|
||||
{
|
||||
return (_pendingData != null);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function forcedMove (sceneId :int) :void
|
||||
{
|
||||
// if we're in the middle of a move, we can't abort it or we will screw everything up, so
|
||||
// just finish up what we're doing and assume that the repeated move request was the
|
||||
// spurious one as it would be in the case of lag causing rapid-fire repeat requests
|
||||
if (movePending()) {
|
||||
if (_pendingData.sceneId == sceneId) {
|
||||
log.info("Dropping forced move because we have a move pending",
|
||||
"pendId", _pendingData.sceneId, "reqId", sceneId);
|
||||
} else {
|
||||
log.info("Delaying forced move because we have a move pending",
|
||||
"pendId", _pendingData.sceneId, "reqId", sceneId);
|
||||
addPendingForcedMove(function() :void {
|
||||
forcedMove(sceneId);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Moving at request of server", "sceneId", sceneId);
|
||||
|
||||
// clear out our old scene and place data
|
||||
didLeaveScene();
|
||||
|
||||
// move to the new scene
|
||||
moveTo(sceneId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the moveHandler for use in recoverFailedMove.
|
||||
*/
|
||||
public function setMoveHandler (handler :SceneDirector_MoveHandler) :void
|
||||
{
|
||||
if (_moveHandler != null) {
|
||||
log.warning("Requested to set move handler, but we've already got one. The " +
|
||||
"conflicting entities will likely need to perform more sophisticated " +
|
||||
"coordination to deal with failures.", "old", _moveHandler, "new", handler);
|
||||
|
||||
} else {
|
||||
_moveHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when something breaks down in the process of performing a <code>moveTo</code>
|
||||
* request.
|
||||
*/
|
||||
public function recoverFailedMove (placeId :int) :void
|
||||
{
|
||||
// we'll need this momentarily
|
||||
var sceneId :int = _sceneId;
|
||||
|
||||
// clear out our now bogus scene tracking info
|
||||
clearScene();
|
||||
|
||||
// if we were previously somewhere (and that somewhere isn't where we just tried to go),
|
||||
// try going back to that happy place
|
||||
if (_previousSceneId != -1 && _previousSceneId != sceneId) {
|
||||
// if we have a move handler use that
|
||||
if (_moveHandler != null) {
|
||||
_moveHandler.recoverMoveTo(_previousSceneId);
|
||||
|
||||
} else {
|
||||
moveTo(_previousSceneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
|
||||
// clear out our business
|
||||
clearScene();
|
||||
_scache.clear();
|
||||
_pendingData = null;
|
||||
_previousSceneId = -1;
|
||||
_sservice = null;
|
||||
}
|
||||
|
||||
public function cancelMoveRequest () :void
|
||||
{
|
||||
_pendingData = null;
|
||||
handlePendingForcedMove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues the scene move request using information from the supplied pending data.
|
||||
*/
|
||||
protected function sendMoveRequest () :void
|
||||
{
|
||||
// check the version of our cached copy of the scene to which we're requesting to move; if
|
||||
// we were unable to load it, assume a cached version of zero
|
||||
var sceneVers :int = 0;
|
||||
if (_pendingData.model != null) {
|
||||
sceneVers = _pendingData.model.version;
|
||||
}
|
||||
|
||||
// issue a moveTo request
|
||||
log.info("Issuing moveTo(" + _pendingData.sceneId + ", " + sceneVers + ").");
|
||||
_sservice.moveTo(_pendingData.sceneId, sceneVers, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pending scene move request. Derived classes may wish to extend this data with
|
||||
* additional information to be tracked during movement between scenes. This is encapsulated so
|
||||
* that if a scene move requires a switch to a new server, all necessary data can be properly
|
||||
* tracked during the server switch.
|
||||
*/
|
||||
protected function createPendingData () :PendingData
|
||||
{
|
||||
return new PendingData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears out our current scene information and releases the scene model for the loaded scene
|
||||
* back to the cache.
|
||||
*/
|
||||
protected function clearScene () :void
|
||||
{
|
||||
// clear out our scene id info
|
||||
_sceneId = -1;
|
||||
|
||||
// clear out our references
|
||||
_model = null;
|
||||
_scene = null;
|
||||
}
|
||||
|
||||
public function addPendingForcedMove (move :Function) :void
|
||||
{
|
||||
_pendingForcedMoves.push(move);
|
||||
}
|
||||
|
||||
protected function handlePendingForcedMove () :void
|
||||
{
|
||||
if (!_pendingForcedMoves.length == 0) {
|
||||
_ctx.getClient().callLater(_pendingForcedMoves.pop());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a scene from the repository. If the scene is cached, it will be returned from the
|
||||
* cache instead.
|
||||
*/
|
||||
protected function loadSceneModel (sceneId :int) :SceneModel
|
||||
{
|
||||
// first look in the model cache
|
||||
var model :SceneModel = (_scache.get(sceneId) as SceneModel);
|
||||
|
||||
// load from the repository if it's not cached
|
||||
if (model == null) {
|
||||
try {
|
||||
model = _screp.loadSceneModel(sceneId);
|
||||
_scache.put(sceneId, model);
|
||||
|
||||
} catch (nsse :NoSuchSceneError) {
|
||||
// nothing special here, just fall through and return null
|
||||
|
||||
} catch (ioe :IOError) {
|
||||
// complain first, then return null
|
||||
log.warning("Error loading scene", "scid", sceneId, "error", ioe);
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persist the scene model to the clientside persistant cache.
|
||||
*/
|
||||
protected function persistSceneModel (model :SceneModel) :void
|
||||
{
|
||||
try {
|
||||
_screp.storeSceneModel(model);
|
||||
} catch (ioe :IOError) {
|
||||
log.warning("Failed to update repository with updated scene",
|
||||
"sceneId", model.sceneId, "nvers", model.version, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
// from BasicDirector
|
||||
override protected function registerServices (client :Client) :void
|
||||
{
|
||||
client.addServiceGroup(SceneCodes.WHIRLED_GROUP);
|
||||
}
|
||||
|
||||
// from BasicDirector
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
// get a handle on our scene service
|
||||
_sservice = (client.requireService(SceneService) as SceneService);
|
||||
}
|
||||
|
||||
/** Access to general client services. */
|
||||
protected var _wctx :WhirledContext;
|
||||
|
||||
/** Access to our scene services. */
|
||||
protected var _sservice :SceneService;
|
||||
|
||||
/** The client's active location director. */
|
||||
protected var _locdir :LocationDirector;
|
||||
|
||||
/** The entity via which we load scene data. */
|
||||
protected var _screp :SceneRepository;
|
||||
|
||||
/** The entity we use to create scenes from scene models. */
|
||||
protected var _fact :SceneFactory;
|
||||
|
||||
/** A cache of scene model information. */
|
||||
protected var _scache :Map = Maps.newBuilder(int).makeLR(5).build();
|
||||
|
||||
/** The display scene object for the scene we currently occupy. */
|
||||
protected var _scene :Scene;
|
||||
|
||||
/** The scene model for the scene we currently occupy. */
|
||||
protected var _model :SceneModel;
|
||||
|
||||
/** The id of the scene we currently occupy. */
|
||||
protected var _sceneId :int = -1;
|
||||
|
||||
/** Information for the scene for which we have an outstanding moveTo request, or null if we
|
||||
* have no outstanding request. */
|
||||
protected var _pendingData :PendingData;
|
||||
|
||||
/** The id of the scene we previously occupied. */
|
||||
protected var _previousSceneId :int = -1;
|
||||
|
||||
/** Reference to our move handler. */
|
||||
protected var _moveHandler :SceneDirector_MoveHandler = null;
|
||||
|
||||
/** Forced move actions we should take once we complete the move we're in the middle of. */
|
||||
protected var _pendingForcedMoves :Array = [];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
/**
|
||||
* Used to recover from a problem after a completed moveTo.
|
||||
*/
|
||||
public interface SceneDirector_MoveHandler
|
||||
{
|
||||
/**
|
||||
* Should instruct the client to move the last known working
|
||||
* location (as well as clean up after the failed moveTo request).
|
||||
*/
|
||||
function recoverMoveTo (sceneId :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationReceiver;
|
||||
|
||||
/**
|
||||
* Defines, for the scene services, a set of notifications delivered
|
||||
* asynchronously by the server to the client.
|
||||
*/
|
||||
public interface SceneReceiver extends InvocationReceiver
|
||||
{
|
||||
/**
|
||||
* Used to communicate a required move notification to the client. The
|
||||
* server will have removed the client from their existing scene
|
||||
* and the client is then responsible for generating a {@link
|
||||
* SceneService#moveTo} request to move to the new scene.
|
||||
*/
|
||||
function forcedMove (sceneId :int) :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SceneService interface.
|
||||
*/
|
||||
public interface SceneService extends InvocationService
|
||||
{
|
||||
// from Java interface SceneService
|
||||
function moveTo (arg1 :int, arg2 :int, arg3 :SceneService_SceneMoveListener) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SceneService_SceneMoveListener interface.
|
||||
*/
|
||||
public interface SceneService_SceneMoveListener
|
||||
extends InvocationService_InvocationListener
|
||||
{
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveRequiresServerSwitch (arg1 :String, arg2 :TypedArray /* of int */) :void
|
||||
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveSucceeded (arg1 :int, arg2 :PlaceConfig) :void
|
||||
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveSucceededWithScene (arg1 :int, arg2 :PlaceConfig, arg3 :SceneModel) :void
|
||||
|
||||
// from Java SceneService_SceneMoveListener
|
||||
function moveSucceededWithUpdates (arg1 :int, arg2 :PlaceConfig, arg3 :TypedArray /* of class com.threerings.whirled.data.SceneUpdate */) :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.client.persist {
|
||||
|
||||
import flash.errors.IOError;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* The scene repository provides access to a persistent repository of scene information.
|
||||
*
|
||||
* @see SceneModel
|
||||
*/
|
||||
public interface SceneRepository
|
||||
{
|
||||
/**
|
||||
* Fetches the model for the scene with the specified id.
|
||||
*
|
||||
* @exception IOError thrown if an error occurs attempting to load the scene data.
|
||||
* @exception NoSuchSceneError thrown if no scene exists with the specified scene id.
|
||||
*/
|
||||
function loadSceneModel (sceneId :int) :SceneModel;
|
||||
//throws IOError, NoSuchSceneError;
|
||||
|
||||
/**
|
||||
* Updates or inserts this scene model as appropriate.
|
||||
*
|
||||
* @exception IOError thrown if an error occurs attempting to access the repository.
|
||||
*/
|
||||
function storeSceneModel (model :SceneModel) :void;
|
||||
//throws IOError;
|
||||
|
||||
/**
|
||||
* Deletes the specified scene model from the repository.
|
||||
*
|
||||
* @exception IOError thrown if an error occurs attempting to access the repository.
|
||||
*/
|
||||
function deleteSceneModel (sceneId :int) :void;
|
||||
//throws IOError;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Cloneable;
|
||||
|
||||
/**
|
||||
* An interface that must be implemented by auxiliary scene models.
|
||||
*/
|
||||
public interface AuxModel extends Streamable, Cloneable
|
||||
{
|
||||
// no new methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
/**
|
||||
* The default scene config simply causes the default scene manager and controller to be created. A
|
||||
* user of the Whirled services would most likely extend the default scene config.
|
||||
*
|
||||
* <p> Note that this place config won't even work on the client side because it instantiates a
|
||||
* SceneController which is an abstract class. It is used only for testing the server side and as a
|
||||
* placeholder in case standard scene configuration information is one day needed. </p>
|
||||
*/
|
||||
public class DefaultSceneConfig extends PlaceConfig
|
||||
{
|
||||
public function DefaultSceneConfig ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function getManagerClassName () :String
|
||||
{
|
||||
return "com.threerings.whirled.server.SceneManager";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
/**
|
||||
* This interface makes available basic scene information. At this basic
|
||||
* level, not much information is available, but extensions to this
|
||||
* interface begin to create a more comprehensive picture of a scene in a
|
||||
* system built from the Whirled services.
|
||||
*/
|
||||
public interface Scene
|
||||
{
|
||||
/**
|
||||
* Returns the unique identifier for this scene.
|
||||
*/
|
||||
function getId () :int;
|
||||
|
||||
/**
|
||||
* Returns the human readable name of this scene.
|
||||
*/
|
||||
function getName () :String;
|
||||
|
||||
/**
|
||||
* Returns the version number of this scene.
|
||||
*/
|
||||
function getVersion () :int;
|
||||
|
||||
/**
|
||||
* Returns the place config that can be used to determine which place
|
||||
* controller instance should be used to display this scene as well as
|
||||
* to obtain runtime configuration information.
|
||||
*/
|
||||
function getPlaceConfig () :PlaceConfig;
|
||||
|
||||
/**
|
||||
* Sets this scene's unique identifier.
|
||||
*/
|
||||
function setId (sceneId :int) :void;
|
||||
|
||||
/**
|
||||
* Sets the human readable name of this scene.
|
||||
*/
|
||||
function setName (name :String) :void;
|
||||
|
||||
/**
|
||||
* Sets this scene's version number.
|
||||
*/
|
||||
function setVersion (version :int) :void;
|
||||
|
||||
/**
|
||||
* Called to inform the scene that an update has been received while
|
||||
* the scene was resolved and active. The update should be applied to
|
||||
* the underlying scene model and any derivative data should be
|
||||
* appropriately updated.
|
||||
*/
|
||||
function updateReceived (update :SceneUpdate) :void;
|
||||
|
||||
/**
|
||||
* Returns the scene model from which this scene was created.
|
||||
*/
|
||||
function getSceneModel () :SceneModel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.LocationCodes;
|
||||
|
||||
/**
|
||||
* Contains codes used by the scene invocation services.
|
||||
*/
|
||||
public class SceneCodes extends LocationCodes
|
||||
{
|
||||
/** Defines our invocation services group. */
|
||||
public static const WHIRLED_GROUP :String = "whirled";
|
||||
|
||||
/** The message identifier for scene update messages. */
|
||||
public static const SCENE_UPDATE :String = "scene_update";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.util.Log;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
/**
|
||||
* An implementation of the {@link Scene} interface.
|
||||
*/
|
||||
public class SceneImpl implements Scene
|
||||
{
|
||||
/**
|
||||
* Creates an instance that will obtain data from the supplied scene
|
||||
* model and place config.
|
||||
*/
|
||||
public function SceneImpl (
|
||||
model :SceneModel = null, config :PlaceConfig = null)
|
||||
{
|
||||
if (model != null) {
|
||||
_model = model;
|
||||
_config = config;
|
||||
|
||||
} else {
|
||||
_model = SceneModel.blankSceneModel();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getId () :int
|
||||
{
|
||||
return _model.sceneId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getName () :String
|
||||
{
|
||||
return _model.name;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getVersion () :int
|
||||
{
|
||||
return _model.version;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public function getPlaceConfig () :PlaceConfig
|
||||
{
|
||||
return _config;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setId (sceneId :int) :void
|
||||
{
|
||||
_model.sceneId = sceneId;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setName (name :String) :void
|
||||
{
|
||||
_model.name = name;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function setVersion (version :int) :void
|
||||
{
|
||||
_model.version = version;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function updateReceived (update :SceneUpdate) :void
|
||||
{
|
||||
try {
|
||||
// validate and apply the update
|
||||
update.validate(_model);
|
||||
update.apply(_model);
|
||||
} catch (e :Error) {
|
||||
var log :Log = Log.getLog(this);
|
||||
log.warning("Error applying update", "scene", this, "update", update, e);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function getSceneModel () :SceneModel
|
||||
{
|
||||
return _model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
return "[model=" + _model + ", config=" + _config + "]";
|
||||
}
|
||||
|
||||
/** A reference to our scene model. */
|
||||
protected var _model :SceneModel;
|
||||
|
||||
/** A reference to our place configuration. */
|
||||
protected var _config :PlaceConfig;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
|
||||
import com.threerings.whirled.client.SceneService;
|
||||
import com.threerings.whirled.client.SceneService_SceneMoveListener;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>SceneService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class SceneMarshaller extends InvocationMarshaller
|
||||
implements SceneService
|
||||
{
|
||||
/** The method id used to dispatch <code>moveTo</code> requests. */
|
||||
public static const MOVE_TO :int = 1;
|
||||
|
||||
// from interface SceneService
|
||||
public function moveTo (arg1 :int, arg2 :int, arg3 :SceneService_SceneMoveListener) :void
|
||||
{
|
||||
var listener3 :SceneMarshaller_SceneMoveMarshaller = new SceneMarshaller_SceneMoveMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(MOVE_TO, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), listener3
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.data.InvocationMarshaller_ListenerMarshaller;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.client.SceneService_SceneMoveListener;
|
||||
|
||||
/**
|
||||
* Marshalls instances of the SceneService_SceneMoveMarshaller interface.
|
||||
*/
|
||||
public class SceneMarshaller_SceneMoveMarshaller
|
||||
extends InvocationMarshaller_ListenerMarshaller
|
||||
{
|
||||
/** The method id used to dispatch <code>moveRequiresServerSwitch</code> responses. */
|
||||
public static const MOVE_REQUIRES_SERVER_SWITCH :int = 1;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceeded</code> responses. */
|
||||
public static const MOVE_SUCCEEDED :int = 2;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithScene</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_SCENE :int = 3;
|
||||
|
||||
/** The method id used to dispatch <code>moveSucceededWithUpdates</code> responses. */
|
||||
public static const MOVE_SUCCEEDED_WITH_UPDATES :int = 4;
|
||||
|
||||
// from InvocationMarshaller_ListenerMarshaller
|
||||
override public function dispatchResponse (methodId :int, args :Array) :void
|
||||
{
|
||||
switch (methodId) {
|
||||
case MOVE_REQUIRES_SERVER_SWITCH:
|
||||
(listener as SceneService_SceneMoveListener).moveRequiresServerSwitch(
|
||||
(args[0] as String), (args[1] as TypedArray /* of int */));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED:
|
||||
(listener as SceneService_SceneMoveListener).moveSucceeded(
|
||||
(args[0] as int), (args[1] as PlaceConfig));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_SCENE:
|
||||
(listener as SceneService_SceneMoveListener).moveSucceededWithScene(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as SceneModel));
|
||||
return;
|
||||
|
||||
case MOVE_SUCCEEDED_WITH_UPDATES:
|
||||
(listener as SceneService_SceneMoveListener).moveSucceededWithUpdates(
|
||||
(args[0] as int), (args[1] as PlaceConfig), (args[2] as TypedArray /* of class com.threerings.whirled.data.SceneUpdate */));
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.Cloneable;
|
||||
|
||||
/**
|
||||
* The scene model is the bare bones representation of the data for a
|
||||
* scene in the Whirled system. From the scene model, one would create an
|
||||
* instance of {@link Scene}.
|
||||
*
|
||||
* <p> The scene model is what is loaded from the scene repositories and
|
||||
* what is transmitted over the wire when communicating scenes from the
|
||||
* server to the client.
|
||||
*/
|
||||
public class SceneModel extends SimpleStreamableObject
|
||||
implements Cloneable
|
||||
{
|
||||
/** This scene's unique identifier. */
|
||||
public var sceneId :int;
|
||||
|
||||
/** The human readable name of this scene. */
|
||||
public var name :String;
|
||||
|
||||
/** The version number of this scene. Versions are incremented
|
||||
* whenever modifications are made to a scene so that clients can
|
||||
* determine whether or not they have the latest version of a
|
||||
* scene. */
|
||||
public var version :int;
|
||||
|
||||
/** Auxiliary scene model information. */
|
||||
public var auxModels :TypedArray = TypedArray.create(AuxModel);
|
||||
|
||||
/**
|
||||
* Creates and returns a blank scene model.
|
||||
*/
|
||||
public static function blankSceneModel () :SceneModel
|
||||
{
|
||||
var model :SceneModel = new SceneModel();
|
||||
populateBlankSceneModel(model);
|
||||
return model;
|
||||
}
|
||||
|
||||
public function SceneModel ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified auxiliary model to this scene model.
|
||||
*/
|
||||
public function addAuxModel (auxModel :AuxModel) :void
|
||||
{
|
||||
auxModels.push(auxModel);
|
||||
}
|
||||
|
||||
// documentation inherited from interface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
var clazz :Class = ClassUtil.getClass(this);
|
||||
var model :SceneModel = new clazz();
|
||||
|
||||
model.sceneId = sceneId;
|
||||
model.name = name;
|
||||
model.version = version;
|
||||
|
||||
for each (var aux :AuxModel in auxModels) {
|
||||
model.addAuxModel(aux.clone() as AuxModel);
|
||||
}
|
||||
return model;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
sceneId = ins.readInt();
|
||||
name = (ins.readField(String) as String);
|
||||
version = ins.readInt();
|
||||
auxModels = TypedArray(ins.readObject());
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(sceneId);
|
||||
out.writeField(name);
|
||||
out.writeInt(version);
|
||||
out.writeObject(auxModels);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a blank scene model with blank values.
|
||||
*/
|
||||
protected static function populateBlankSceneModel (model :SceneModel) :void
|
||||
{
|
||||
model.sceneId = -1;
|
||||
model.name = "<blank>";
|
||||
model.version = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
public class SceneObject extends PlaceObject
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.Place;
|
||||
|
||||
/**
|
||||
* Extends {@link Place} with scene information.
|
||||
*/
|
||||
public class ScenePlace extends Place
|
||||
{
|
||||
/** The id of the scene occupied by the body. */
|
||||
public var sceneId :int;
|
||||
|
||||
/**
|
||||
* Returns the scene id occupied by the supplied body or -1 if the body is not in a scene.
|
||||
*/
|
||||
public static function getSceneId (bobj :BodyObject) :int
|
||||
{
|
||||
return (bobj.location is ScenePlace) ? (bobj.location as ScenePlace).sceneId : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a scene place with the supplied {@link SceneObject} oid and scene id.
|
||||
*/
|
||||
public function ScenePlace (sceneOid :int = 0, sceneID :int = 0)
|
||||
{
|
||||
super(sceneOid);
|
||||
this.sceneId = sceneId;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
sceneId = ins.readInt();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(sceneId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.data {
|
||||
|
||||
import flash.errors.IllegalOperationError;
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Joiner;
|
||||
import com.threerings.util.Log;
|
||||
|
||||
/**
|
||||
* Used to encapsulate updates to scenes in such a manner that updates can
|
||||
* be stored persistently and sent to clients to update their own local
|
||||
* copies of scenes.
|
||||
*/
|
||||
public class SceneUpdate
|
||||
implements Streamable, Cloneable
|
||||
{
|
||||
public function SceneUpdate ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies this update to the specified scene model. Derived classes
|
||||
* will want to override this method and apply updates of their own,
|
||||
* being sure to call <code>super.apply</code>.
|
||||
*/
|
||||
public function apply (model :SceneModel) :void
|
||||
{
|
||||
// increment the version; disallowing integer overflow
|
||||
model.version = Math.max(_targetVersion + 1, model.version);
|
||||
|
||||
// sanity check for the amazing two billion updates
|
||||
if (model.version == _targetVersion) {
|
||||
Log.getLog(this).warning("Egads! This scene has been updated two" +
|
||||
" billion times [model=" + model + ", update=" + this + "].");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scene id for which this update is appropriate.
|
||||
*/
|
||||
public function getSceneId () :int
|
||||
{
|
||||
return _targetId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scene version for which this update is appropriate.
|
||||
*/
|
||||
public function getSceneVersion () :int
|
||||
{
|
||||
return _targetVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
var j :Joiner = Joiner.createFor(this);
|
||||
toStringJoiner(j);
|
||||
return j.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this scene update such that it will operate on a scene
|
||||
* with the specified target scene and version number.
|
||||
*
|
||||
* @param targetId the id of the scene on which we are to operate.
|
||||
* @param targetVersion the version of the scene on which we are to
|
||||
* operate.
|
||||
*/
|
||||
public function init (targetId :int, targetVersion :int) :void
|
||||
{
|
||||
_targetId = targetId;
|
||||
_targetVersion = targetVersion;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(_targetId);
|
||||
out.writeInt(_targetVersion);
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
_targetId = ins.readInt();
|
||||
_targetVersion = ins.readInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to ensure that the scene is in the appropriate state prior
|
||||
* to applying the update.
|
||||
*
|
||||
* @exception IllegalStateException thrown if the update cannot be
|
||||
* applied to the scene because it is not in a valid state
|
||||
* (appropriate previous updates were not applied, it's the wrong kind
|
||||
* of scene, etc.).
|
||||
*/
|
||||
public function validate (model :SceneModel) :void
|
||||
//throws IllegalStateException
|
||||
{
|
||||
if (model.sceneId != _targetId) {
|
||||
throw new IllegalOperationError("Wrong target scene, expected id " +
|
||||
_targetId + " got id " + model.sceneId);
|
||||
|
||||
} else if (model.version != _targetVersion) {
|
||||
throw new IllegalOperationError("Target scene not proper " +
|
||||
"version, expected " + _targetVersion +
|
||||
" got " + model.version);
|
||||
}
|
||||
}
|
||||
|
||||
// from interface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
throw new Error("Not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* An extensible mechanism for generating a string representation of
|
||||
* this instance.
|
||||
*/
|
||||
protected function toStringJoiner (j :Joiner) :void
|
||||
{
|
||||
j.add("sceneId", _targetId, "version", _targetVersion);
|
||||
}
|
||||
|
||||
/** The version number of the scene on which we operate. */
|
||||
protected var _targetId :int;
|
||||
|
||||
/** The version number of the scene on which we operate. */
|
||||
protected var _targetVersion :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.client {
|
||||
|
||||
import com.threerings.whirled.client.SceneController;
|
||||
|
||||
/**
|
||||
* The base spot scene controller class. It is expected that users of the
|
||||
* Whirled Spot services will extend this controller class when creating
|
||||
* specialized controllers for their scenes. Presently there are no basic
|
||||
* scene services provided by this controller, but its existence affords
|
||||
* the addition of such services should they become necessary in the
|
||||
* future.
|
||||
*/
|
||||
public /*abstract*/ class SpotSceneController extends SceneController
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.client {
|
||||
import com.threerings.util.Log;
|
||||
import com.threerings.util.ResultListener;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.ClientEvent;
|
||||
import com.threerings.presents.client.ConfirmAdapter;
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.dobj.DObjectManager;
|
||||
import com.threerings.presents.dobj.ObjectAccessError;
|
||||
import com.threerings.presents.dobj.Subscriber;
|
||||
|
||||
import com.threerings.crowd.chat.client.ChatDirector;
|
||||
import com.threerings.crowd.chat.data.ChatCodes;
|
||||
import com.threerings.crowd.client.CrowdClient;
|
||||
import com.threerings.crowd.client.LocationAdapter;
|
||||
import com.threerings.crowd.client.LocationDirector;
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.whirled.client.SceneDirector;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.ScenePlace;
|
||||
import com.threerings.whirled.spot.data.ClusteredBodyObject;
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
import com.threerings.whirled.spot.data.Portal;
|
||||
import com.threerings.whirled.spot.data.SceneLocation;
|
||||
import com.threerings.whirled.spot.data.SpotCodes;
|
||||
import com.threerings.whirled.spot.data.SpotMarshaller;
|
||||
import com.threerings.whirled.spot.data.SpotScene;
|
||||
import com.threerings.whirled.spot.data.SpotSceneObject;
|
||||
import com.threerings.whirled.util.WhirledContext;
|
||||
|
||||
/**
|
||||
* Extends the standard scene director with facilities to move between locations within a scene.
|
||||
*/
|
||||
public class SpotSceneDirector extends BasicDirector
|
||||
implements Subscriber, AttributeChangeListener
|
||||
{
|
||||
private static const log :Log = Log.getLog(SpotSceneDirector);
|
||||
|
||||
// statically reference classes we require
|
||||
SpotMarshaller;
|
||||
|
||||
/**
|
||||
* Creates a new spot scene director with the specified context and which will cooperate with
|
||||
* the supplied scene director.
|
||||
*
|
||||
* @param ctx the active client context.
|
||||
* @param locdir the location director with which we will be cooperating.
|
||||
* @param scdir the scene director with which we will be cooperating.
|
||||
*/
|
||||
public function SpotSceneDirector (
|
||||
ctx :WhirledContext, locdir :LocationDirector, scdir :SceneDirector)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
_wctx = ctx;
|
||||
_scdir = scdir;
|
||||
|
||||
// wire ourselves up to hear about leave place notifications
|
||||
locdir.addLocationObserver(new LocationAdapter(null, handleSceneChange, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures this spot scene director with a chat director, with which it will coordinate to
|
||||
* implement cluster chatting.
|
||||
*/
|
||||
public function setChatDirector (chatdir :ChatDirector) :void
|
||||
{
|
||||
_chatdir = chatdir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns our current location unless we have a location change pending, in which case our
|
||||
* pending location is returned.
|
||||
*/
|
||||
public function getIntendedLocation () :Location
|
||||
{
|
||||
return (_pendingLoc != null) ? _pendingLoc : _location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that this client move to the location specified by the supplied portal id. A
|
||||
* request will be made and when the response is received, the location observers will be
|
||||
* notified of success or failure.
|
||||
*
|
||||
* @return true if the request was issued, false if it was rejected by a location observer or
|
||||
* because we have another request outstanding.
|
||||
*/
|
||||
public function traversePortal (
|
||||
portalId :int, rl :com.threerings.util.ResultListener = null) :Boolean
|
||||
{
|
||||
// look up the destination scene and location
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to traverse portal when we have no scene " +
|
||||
"[portalId=" + portalId + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// sanity check the server's notion of what scene we're in with our notion of it
|
||||
var sceneId :int = _scdir.getScene().getId();
|
||||
var clSceneId :int = ScenePlace.getSceneId(CrowdClient(_wctx.getClient()).bodyOf());
|
||||
if (sceneId != clSceneId) {
|
||||
log.warning("Client and server differ in opinion of what scene we're in " +
|
||||
"[sSceneId=" + clSceneId + ", cSceneId=" + sceneId + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// find the portal they're talking about
|
||||
var dest :Portal = scene.getPortal(portalId);
|
||||
if (dest == null) {
|
||||
log.warning("Requested to traverse non-existent portal [portalId=" + portalId +
|
||||
", portals=" + scene.getPortals() + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// prepare to move to this scene (sets up pending data)
|
||||
if (!_scdir.prepareMoveTo(dest.targetSceneId, rl)) {
|
||||
log.info("Portal traversal vetoed by scene director [portalId=" + portalId + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check the version of our cached copy of the scene to which we're requesting to move; if
|
||||
// we were unable to load it, assume a cached version of zero
|
||||
var sceneVer :int = 0;
|
||||
var pendingModel :SceneModel = _scdir.getPendingModel();
|
||||
if (pendingModel != null) {
|
||||
sceneVer = pendingModel.version;
|
||||
}
|
||||
|
||||
// issue a traversePortal request
|
||||
log.info("Issuing traversePortal(" + sceneId + ", " + dest + ", " + sceneVer + ").");
|
||||
_sservice.traversePortal(sceneId, portalId, sceneVer, new SceneDirectorWrapper(_scdir));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a request to change our location within the scene to the specified location.
|
||||
*
|
||||
* @param loc the new location to which to move.
|
||||
* @param listener will be notified of success or failure. Most client entities find out about
|
||||
* location changes via changes to the occupant info data, but the initiator of a location
|
||||
* change request can be notified of its success or failure, primarily so that it can act in
|
||||
* anticipation of a successful location change (like by starting a sprite moving toward the
|
||||
* new location), but backtrack if it finds out that the location change failed.
|
||||
*/
|
||||
public function changeLocation (
|
||||
loc :Location, listener :com.threerings.util.ResultListener) :void
|
||||
{
|
||||
// refuse if there's a pending location change or if we're already at the specified
|
||||
// location
|
||||
if (loc.equivalent(_location)) {
|
||||
log.info("Not going to " + loc + "; we're at " + _location +
|
||||
" and we're headed to " + _pendingLoc + ".");
|
||||
if (listener != null) {
|
||||
// This isn't really a failure, it's just a no-op.
|
||||
listener.requestCompleted(_location);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_pendingLoc != null) {
|
||||
log.info("Not going to " + loc + "; we're at " + _location +
|
||||
" and we're headed to " + _pendingLoc + ".");
|
||||
if (listener != null) {
|
||||
// Already moving, best thing to do is ignore it.
|
||||
listener.requestCompleted(_pendingLoc);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to change locations, but we're not currently in any scene " +
|
||||
"[loc=" + loc + "].");
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error("m.cant_get_there"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var sceneId :int = _scdir.getScene().getId();
|
||||
// log.info("Sending changeLocation request [scid=" + sceneId + ", loc=" + loc + "].");
|
||||
|
||||
_pendingLoc = (loc.clone() as Location);
|
||||
var clist :ConfirmAdapter = new ConfirmAdapter(
|
||||
function () :void {
|
||||
_location = _pendingLoc;
|
||||
_pendingLoc = null;
|
||||
if (listener != null) {
|
||||
listener.requestCompleted(_location);
|
||||
}
|
||||
},
|
||||
function (reason :String) :void {
|
||||
_pendingLoc = null;
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error(reason));
|
||||
}
|
||||
});
|
||||
_sservice.changeLocation(sceneId, loc, clist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a request to join the cluster associated with the specified user (starting one if
|
||||
* necessary).
|
||||
*
|
||||
* @param froid the bodyOid of another user; the calling user will be made to join the target
|
||||
* user's cluster.
|
||||
* @param listener will be notified of success or failure.
|
||||
*/
|
||||
public function joinCluster (froid :int, listener :com.threerings.util.ResultListener) :void
|
||||
{
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to join cluster, but we're not currently in any scene " +
|
||||
"[froid=" + froid + "].");
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error("m.cant_get_there"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
log.info("Joining cluster [friend=" + froid + "].");
|
||||
|
||||
_sservice.joinCluster(froid, new ConfirmAdapter(
|
||||
function () :void {
|
||||
if (listener != null) {
|
||||
listener.requestCompleted(null);
|
||||
}
|
||||
},
|
||||
function (reason :String) :void {
|
||||
if (listener != null) {
|
||||
listener.requestFailed(new Error(reason));
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a chat message to the other users in the cluster to which the location that we
|
||||
* currently occupy belongs.
|
||||
*
|
||||
* @return true if a cluster speak message was delivered, false if we are not in a valid
|
||||
* cluster and refused to deliver the request.
|
||||
*/
|
||||
public function requestClusterSpeak (
|
||||
message :String, mode :int = ChatCodes.DEFAULT_MODE) :Boolean
|
||||
{
|
||||
// make sure we're currently in a scene
|
||||
var scene :SpotScene = (_scdir.getScene() as SpotScene);
|
||||
if (scene == null) {
|
||||
log.warning("Requested to speak to cluster, but we're not currently in any scene " +
|
||||
"[message=" + message + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we're part of a cluster
|
||||
if (_self.getClusterOid() <= 0) {
|
||||
log.info("Ignoring cluster speak as we're not in a cluster " +
|
||||
"[cloid=" + _self.getClusterOid() + "].");
|
||||
return false;
|
||||
}
|
||||
|
||||
message = _chatdir.filter(message, null, true);
|
||||
if (message != null) {
|
||||
_sservice.clusterSpeak(message, mode);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function objectAvailable (object :DObject) :void
|
||||
{
|
||||
clearCluster(false);
|
||||
var oid :int = object.getOid();
|
||||
if (oid != _self.getClusterOid()) {
|
||||
// we got it too late, just unsubscribe
|
||||
var omgr :DObjectManager = _wctx.getDObjectManager();
|
||||
omgr.unsubscribeFromObject(oid, this);
|
||||
} else {
|
||||
// it's our new cluster!
|
||||
_clobj = object;
|
||||
if (_chatdir != null) {
|
||||
_chatdir.addAuxiliarySource(object, SpotCodes.CLUSTER_CHAT_TYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function requestFailed (oid :int, cause :ObjectAccessError) :void
|
||||
{
|
||||
log.warning("Unable to subscribe to cluster chat object [oid=" + oid +
|
||||
", cause=" + cause + "].");
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public function attributeChanged (event :AttributeChangedEvent) :void
|
||||
{
|
||||
if (event.getName() == _self.getClusterField() && event.getValue() != event.getOldValue()) {
|
||||
maybeUpdateCluster();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogon (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogon(event);
|
||||
|
||||
var body :BodyObject = CrowdClient(event.getClient()).bodyOf();
|
||||
if (body is ClusteredBodyObject) {
|
||||
// listen to the body
|
||||
body.addListener(this);
|
||||
_self = (body as ClusteredBodyObject);
|
||||
|
||||
// we may need to subscribe to a cluster due to session resumption
|
||||
maybeUpdateCluster();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientObjectDidChange (event :ClientEvent) :void
|
||||
{
|
||||
super.clientObjectDidChange(event);
|
||||
|
||||
var body :BodyObject = CrowdClient(event.getClient()).bodyOf();
|
||||
if (body is ClusteredBodyObject) {
|
||||
// listen to the body
|
||||
body.addListener(this);
|
||||
_self = (body as ClusteredBodyObject);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override public function clientDidLogoff (event :ClientEvent) :void
|
||||
{
|
||||
super.clientDidLogoff(event);
|
||||
|
||||
// clear out our business
|
||||
_location = null;
|
||||
_pendingLoc = null;
|
||||
_sservice = null;
|
||||
clearCluster(true);
|
||||
|
||||
var body :BodyObject = CrowdClient(event.getClient()).bodyOf();
|
||||
if (body is ClusteredBodyObject) {
|
||||
body.removeListener(this);
|
||||
}
|
||||
_self = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
override protected function fetchServices (client :Client) :void
|
||||
{
|
||||
_sservice = (client.requireService(SpotService) as SpotService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we move from one scene to another, or to a non-scene.
|
||||
*/
|
||||
protected function handleSceneChange (plobj :PlaceObject) :void
|
||||
{
|
||||
// determine our location in the new scene if we have one
|
||||
var scloc :SceneLocation = null;
|
||||
var ssobj :SpotSceneObject = (plobj as SpotSceneObject);
|
||||
if (ssobj != null) {
|
||||
scloc = ssobj.occupantLocs.get(
|
||||
CrowdClient(_wctx.getClient()).bodyOf().getOid()) as SceneLocation;
|
||||
}
|
||||
_location = (scloc == null) ? null : scloc.loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if our cluster has changed and does the necessary subscription machinations if
|
||||
* necessary.
|
||||
*/
|
||||
protected function maybeUpdateCluster () :void
|
||||
{
|
||||
var cloid :int = _self.getClusterOid();
|
||||
if ((_clobj == null && cloid <= 0) || (_clobj != null && cloid == _clobj.getOid())) {
|
||||
// our cluster didn't change, we can stop now
|
||||
return;
|
||||
}
|
||||
|
||||
// clear out any old cluster object
|
||||
clearCluster(false);
|
||||
|
||||
// if there's a new cluster object, subscribe to it
|
||||
if (_chatdir != null && cloid > 0) {
|
||||
var omgr :DObjectManager = _wctx.getDObjectManager();
|
||||
// we'll wire up to the chat director when this completes
|
||||
omgr.subscribeToObject(cloid, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience routine to unwire chat for and unsubscribe from our current cluster, if any.
|
||||
*
|
||||
* @param force clear the cluster even if we're still apparently in it.
|
||||
*/
|
||||
protected function clearCluster (force :Boolean) :void
|
||||
{
|
||||
if (_clobj != null && (force || (_clobj.getOid() != _self.getClusterOid()))) {
|
||||
if (_chatdir != null) {
|
||||
_chatdir.removeAuxiliarySource(_clobj);
|
||||
}
|
||||
var omgr :DObjectManager = _wctx.getDObjectManager();
|
||||
omgr.unsubscribeFromObject(_clobj.getOid(), this);
|
||||
_clobj = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** The active client context. */
|
||||
protected var _wctx :WhirledContext;
|
||||
|
||||
/** Access to spot scene services. */
|
||||
protected var _sservice :SpotService;
|
||||
|
||||
/** The scene director with which we are cooperating. */
|
||||
protected var _scdir :SceneDirector;
|
||||
|
||||
/** A casted reference to our clustered body object. */
|
||||
protected var _self :ClusteredBodyObject;
|
||||
|
||||
/** A reference to the chat director with which we coordinate. */
|
||||
protected var _chatdir :ChatDirector;
|
||||
|
||||
/** The location we currently occupy. */
|
||||
protected var _location :Location;
|
||||
|
||||
/** The location to which we have an outstanding change location request. */
|
||||
protected var _pendingLoc :Location;
|
||||
|
||||
/** The cluster chat object for the cluster we currently occupy. */
|
||||
protected var _clobj :DObject;
|
||||
}
|
||||
}
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.client.SceneDirector;
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.spot.client.SpotService_SpotSceneMoveListener;
|
||||
|
||||
class SceneDirectorWrapper
|
||||
implements SpotService_SpotSceneMoveListener
|
||||
{
|
||||
public function SceneDirectorWrapper (scdir :SceneDirector) {
|
||||
_scdir = scdir;
|
||||
}
|
||||
|
||||
public function requestFailed (cause :String) :void {
|
||||
_scdir.requestFailed(cause);
|
||||
}
|
||||
|
||||
public function moveSucceeded (placeId :int, config :PlaceConfig) :void {
|
||||
_scdir.moveSucceeded(placeId, config);
|
||||
}
|
||||
|
||||
public function moveSucceededWithUpdates (
|
||||
placeId :int, config :PlaceConfig, updates :TypedArray) :void{
|
||||
_scdir.moveSucceededWithUpdates(placeId, config, updates);
|
||||
}
|
||||
|
||||
public function moveSucceededWithScene (placeId :int, config :PlaceConfig,
|
||||
model :SceneModel) :void {
|
||||
_scdir.moveSucceededWithScene(placeId, config, model);
|
||||
}
|
||||
|
||||
public function moveRequiresServerSwitch (hostname :String, ports :TypedArray) :void {
|
||||
_scdir.moveRequiresServerSwitch(hostname, ports);
|
||||
}
|
||||
|
||||
public function requestCancelled () :void {
|
||||
_scdir.cancelMoveRequest();
|
||||
}
|
||||
|
||||
protected var _scdir :SceneDirector;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.client {
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
|
||||
import com.threerings.whirled.spot.data.Location;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SpotService interface.
|
||||
*/
|
||||
public interface SpotService extends InvocationService
|
||||
{
|
||||
// from Java interface SpotService
|
||||
function changeLocation (arg1 :int, arg2 :Location, arg3 :InvocationService_ConfirmListener) :void;
|
||||
|
||||
// from Java interface SpotService
|
||||
function clusterSpeak (arg1 :String, arg2 :int) :void;
|
||||
|
||||
// from Java interface SpotService
|
||||
function joinCluster (arg1 :int, arg2 :InvocationService_ConfirmListener) :void;
|
||||
|
||||
// from Java interface SpotService
|
||||
function traversePortal (arg1 :int, arg2 :int, arg3 :int, arg4 :SpotService_SpotSceneMoveListener) :void;
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.client {
|
||||
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_InvocationListener;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
|
||||
/**
|
||||
* An ActionScript version of the Java SpotService_SpotSceneMoveListener interface.
|
||||
*/
|
||||
public interface SpotService_SpotSceneMoveListener
|
||||
extends InvocationService_InvocationListener
|
||||
{
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveRequiresServerSwitch (arg1 :String, arg2 :TypedArray /* of int */) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveSucceeded (arg1 :int, arg2 :PlaceConfig) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveSucceededWithScene (arg1 :int, arg2 :PlaceConfig, arg3 :SceneModel) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function moveSucceededWithUpdates (arg1 :int, arg2 :PlaceConfig, arg3 :TypedArray /* of class com.threerings.whirled.data.SceneUpdate */) :void
|
||||
|
||||
// from Java SpotService_SpotSceneMoveListener
|
||||
function requestCancelled () :void
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
/**
|
||||
* Contains information on clusters.
|
||||
*/
|
||||
public class Cluster
|
||||
implements DSet_Entry, Streamable, Hashable
|
||||
{
|
||||
/** The bounding rectangle of this cluster. */
|
||||
public var x :int;
|
||||
public var y :int;
|
||||
public var width :int;
|
||||
public var height :int;
|
||||
|
||||
/** A unique identifier for this cluster (also the distributed object
|
||||
* id of the cluster chat object). */
|
||||
public var clusterOid :int;
|
||||
|
||||
public function Cluster ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
// from Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return clusterOid;
|
||||
}
|
||||
|
||||
// from Hashable
|
||||
public function equals (o :Object) :Boolean
|
||||
{
|
||||
return (o is Cluster) && ((o as Cluster).clusterOid == this.clusterOid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this instance.
|
||||
*/
|
||||
public function toString () :String
|
||||
{
|
||||
return "x=" + x + ", y=" + y + ", width=" + width + ", height=" + height +
|
||||
", clusterOid=" + clusterOid;
|
||||
}
|
||||
|
||||
// documentation inherited from interface DSet_Entry
|
||||
public function getKey () :Object
|
||||
{
|
||||
return clusterOid;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
x = ins.readInt();
|
||||
y = ins.readInt();
|
||||
width = ins.readInt();
|
||||
height = ins.readInt();
|
||||
|
||||
clusterOid = ins.readInt();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Streamable
|
||||
public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
out.writeInt(x);
|
||||
out.writeInt(y);
|
||||
out.writeInt(width);
|
||||
out.writeInt(height);
|
||||
|
||||
out.writeInt(clusterOid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.dobj.OidList;
|
||||
|
||||
/**
|
||||
* Used to dispatch chat in clusters.
|
||||
*/
|
||||
public class ClusterObject extends DObject
|
||||
{
|
||||
// AUTO-GENERATED: FIELDS START
|
||||
/** The field name of the <code>occupants</code> field. */
|
||||
public static const OCCUPANTS :String = "occupants";
|
||||
// AUTO-GENERATED: FIELDS END
|
||||
|
||||
/**
|
||||
* Tracks the oid of the body objects that occupy this cluster.
|
||||
*/
|
||||
public var occupants :OidList = new OidList();
|
||||
|
||||
// // AUTO-GENERATED: METHODS START
|
||||
// /**
|
||||
// * Requests that <code>oid</code> be added to the <code>occupants</code>
|
||||
// * oid list. The list will not change until the event is actually
|
||||
// * propagated through the system.
|
||||
// */
|
||||
// public function addToOccupants (oid :int) :void
|
||||
// {
|
||||
// requestOidAdd(OCCUPANTS, oid);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Requests that <code>oid</code> be removed from the
|
||||
// * <code>occupants</code> oid list. The list will not change until the
|
||||
// * event is actually propagated through the system.
|
||||
// */
|
||||
// public function removeFromOccupants (oid :int) :void
|
||||
// {
|
||||
// requestOidRemove(OCCUPANTS, oid);
|
||||
// }
|
||||
// // AUTO-GENERATED: METHODS END
|
||||
//
|
||||
// override public function writeObject (out :ObjectOutputStream) :void
|
||||
// {
|
||||
// super.writeObject(out);
|
||||
//
|
||||
// out.writeObject(occupants);
|
||||
// }
|
||||
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
|
||||
occupants = OidList(ins.readObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
|
||||
/**
|
||||
* Defines some required methods for a {@link BodyObject} that is to participate in the Whirled
|
||||
* Spot system.
|
||||
*/
|
||||
public interface ClusteredBodyObject
|
||||
{
|
||||
/**
|
||||
* Returns the field name of the cluster oid distributed object field.
|
||||
*/
|
||||
function getClusterField () :String;
|
||||
|
||||
/**
|
||||
* Returns the oid of the cluster to which this user currently
|
||||
* belongs.
|
||||
*/
|
||||
function getClusterOid () :int;
|
||||
|
||||
// /**
|
||||
// * Sets the oid of the cluster to which this user currently belongs.
|
||||
// */
|
||||
// function setClusterOid (clusterOid :int) :void;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.Streamable;
|
||||
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
/**
|
||||
* Contains information on a scene occupant's position and orientation.
|
||||
*/
|
||||
public interface Location extends Cloneable, Streamable, Hashable
|
||||
{
|
||||
/**
|
||||
* Get a new Location instance that is equals() to this one but that
|
||||
* has an orientation facing the opposite direction.
|
||||
*/
|
||||
function getOpposite () :Location;
|
||||
|
||||
/**
|
||||
* Two locations are equivalent if they specify the same location
|
||||
* and orientation.
|
||||
*/
|
||||
function equivalent (other :Location) :Boolean;
|
||||
|
||||
/** Two locations are equals by coordinates only. */
|
||||
//function equals (other :Object) :Boolean;
|
||||
|
||||
/** The hashcode should be based on coordinates only. */
|
||||
//function hashCode () :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.TypedArray;
|
||||
|
||||
import com.threerings.whirled.data.SceneModel;
|
||||
import com.threerings.whirled.data.SceneUpdate;
|
||||
|
||||
/**
|
||||
* A scene update to add/remove portals.
|
||||
*/
|
||||
public class ModifyPortalsUpdate extends SceneUpdate
|
||||
{
|
||||
/** The portals to be removed from the room. */
|
||||
public var portalsRemoved :TypedArray;
|
||||
|
||||
/** The portals to be added to the scene. */
|
||||
public var portalsAdded :TypedArray;
|
||||
|
||||
public function ModifyPortalsUpdate ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
override public function apply (model :SceneModel) :void
|
||||
{
|
||||
super.apply(model);
|
||||
|
||||
// extract the spot scene model
|
||||
var spotModel :SpotSceneModel = SpotSceneModel.getSceneModel(model);
|
||||
|
||||
var portal :Portal;
|
||||
if (portalsRemoved != null) {
|
||||
for each (portal in portalsRemoved) {
|
||||
spotModel.removePortal(portal);
|
||||
}
|
||||
}
|
||||
if (portalsAdded != null) {
|
||||
for each (portal in portalsAdded) {
|
||||
spotModel.addPortal(portal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the update with all necessary data.
|
||||
*/
|
||||
public function initialize (
|
||||
targetId :int, targetVersion :int, removed :TypedArray,
|
||||
added :TypedArray) :void
|
||||
{
|
||||
init(targetId, targetVersion);
|
||||
|
||||
portalsRemoved = removed;
|
||||
portalsAdded = added;
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
portalsRemoved = TypedArray(ins.readObject());
|
||||
portalsAdded = TypedArray(ins.readObject());
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeObject(portalsRemoved);
|
||||
out.writeObject(portalsAdded);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
import com.threerings.util.ClassUtil;
|
||||
import com.threerings.util.Cloneable;
|
||||
import com.threerings.util.Hashable;
|
||||
import com.threerings.util.Joiner;
|
||||
|
||||
/**
|
||||
* Represents an exit to another scene. A body sprite would walk over to a
|
||||
* portal's coordinates and then either proceed off of the edge of the
|
||||
* display, or open a door and walk through it, or fizzle away in a Star
|
||||
* Trekkian transporter style or whatever is appropriate for the game in
|
||||
* question. It contains information on the scene to which the body exits
|
||||
* when using this portal and the location at which the body sprite should
|
||||
* appear in that target scene.
|
||||
*/
|
||||
public class Portal extends SimpleStreamableObject
|
||||
implements Cloneable, Hashable
|
||||
{
|
||||
/** This portal's unique identifier. */
|
||||
public var portalId :int;
|
||||
|
||||
/** The location of the portal.
|
||||
* This field is present on client and server, it is streamed specially. */
|
||||
public var loc :Location;
|
||||
|
||||
/** The scene identifier of the scene to which a body will exit when
|
||||
* they "use" this portal. */
|
||||
public var targetSceneId :int;
|
||||
|
||||
/** The portal identifier of the portal at which a body will enter
|
||||
* the target scene when they "use" this portal, or -1 to specify
|
||||
* that the body enters on the default portal, whatever id it is. */
|
||||
public var targetPortalId :int;
|
||||
|
||||
public function Portal ()
|
||||
{
|
||||
// nothing needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a location instance configured with the location and
|
||||
* opposite orientation of this portal. This is useful for when a body
|
||||
* is entering a scene at a portal and we want them to face the
|
||||
* opposite direction (as they are entering via the portal rather than
|
||||
* leaving, which is the natural "orientation" of a portal).
|
||||
*/
|
||||
public function getOppLocation () :Location
|
||||
{
|
||||
return loc.getOpposite();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return portalId;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Cloneable
|
||||
public function clone () :Object
|
||||
{
|
||||
var p :Portal = (ClassUtil.newInstance(this) as Portal);
|
||||
p.portalId = portalId;
|
||||
p.loc = loc;
|
||||
p.targetSceneId = targetSceneId;
|
||||
p.targetPortalId = targetPortalId;
|
||||
return p;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
return (other is Portal) &&
|
||||
((other as Portal).portalId == portalId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a location instance configured with the location and
|
||||
* orientation of this portal.
|
||||
*/
|
||||
public function getLocation () :Location
|
||||
{
|
||||
return (loc.clone() as Location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the portal has a potentially valid target scene and
|
||||
* portal id (they are not guaranteed to exist, but they are at least
|
||||
* potentially valid values rather than 0).
|
||||
*/
|
||||
public function isValid () :Boolean
|
||||
{
|
||||
return (targetSceneId > 0) &&
|
||||
// the target portal must be positive, or -1
|
||||
((targetPortalId > 0) || (targetPortalId == -1));
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
portalId = ins.readShort();
|
||||
loc = Location(ins.readObject());
|
||||
targetSceneId = ins.readInt();
|
||||
targetPortalId = ins.readShort();
|
||||
}
|
||||
|
||||
// from interface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeShort(portalId);
|
||||
out.writeObject(loc);
|
||||
out.writeInt(targetSceneId);
|
||||
out.writeShort(targetPortalId);
|
||||
}
|
||||
|
||||
// from SimpleStreamableObject
|
||||
override protected function toStringJoiner (j :Joiner): void
|
||||
{
|
||||
// no super
|
||||
j.add("id", portalId, "destScene", targetSceneId, "loc", loc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
import com.threerings.io.SimpleStreamableObject;
|
||||
|
||||
import com.threerings.util.Hashable;
|
||||
|
||||
import com.threerings.presents.dobj.DSet_Entry;
|
||||
|
||||
/**
|
||||
* Extends {@link Location} with the data and functionality needed to
|
||||
* represent a particular user's location in a scene.
|
||||
*/
|
||||
public class SceneLocation extends SimpleStreamableObject
|
||||
implements DSet_Entry, Hashable
|
||||
{
|
||||
/** The oid of the body that occupies this location. */
|
||||
public var bodyOid :int;
|
||||
|
||||
/** The actual location, which is interpreted by the display system. */
|
||||
public var loc :Location;
|
||||
|
||||
/**
|
||||
* Creates a scene location with the specified information.
|
||||
*/
|
||||
public function SceneLocation (loc :Location = null, bodyOid :int = 0)
|
||||
{
|
||||
this.loc = loc;
|
||||
this.bodyOid = bodyOid;
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function hashCode () :int
|
||||
{
|
||||
return loc.hashCode();
|
||||
}
|
||||
|
||||
// documentation inherited from interface Hashable
|
||||
public function equals (other :Object) :Boolean
|
||||
{
|
||||
return (other is SceneLocation) &&
|
||||
this.loc.equals((other as SceneLocation).loc);
|
||||
}
|
||||
|
||||
// documentation inherited from interface DSet_Entry
|
||||
public function getKey () :Object
|
||||
{
|
||||
return bodyOid;
|
||||
}
|
||||
|
||||
// documentation inherited from superinterface Streamable
|
||||
override public function readObject (ins :ObjectInputStream) :void
|
||||
{
|
||||
super.readObject(ins);
|
||||
bodyOid = ins.readInt();
|
||||
loc = Location(ins.readObject());
|
||||
}
|
||||
|
||||
// documentation inherited from superinterface Streamable
|
||||
override public function writeObject (out :ObjectOutputStream) :void
|
||||
{
|
||||
super.writeObject(out);
|
||||
out.writeInt(bodyOid);
|
||||
out.writeObject(loc);
|
||||
}
|
||||
|
||||
/** Used for {@link #getKey}. */
|
||||
protected var _key :int;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.crowd.chat.data.ChatCodes;
|
||||
|
||||
import com.threerings.whirled.data.SceneCodes;
|
||||
|
||||
/**
|
||||
* Contains codes used by the Spot invocation services.
|
||||
*/
|
||||
public class SpotCodes extends SceneCodes /*, ChatCodes */
|
||||
{
|
||||
/** An error code indicating that the portal specified in a
|
||||
* traversePortal request does not exist. */
|
||||
public static const NO_SUCH_PORTAL :String = "m.no_such_portal";
|
||||
|
||||
/** An error code indicating that a location is occupied. Usually
|
||||
* generated by a failed changeLoc request. */
|
||||
public static const LOCATION_OCCUPIED :String = "m.location_occupied";
|
||||
|
||||
/** An error code indicating that a location is not valid. Usually
|
||||
* generated by a failed changeLoc request. */
|
||||
public static const INVALID_LOCATION :String = "m.invalid_location";
|
||||
|
||||
/** An error code indicating that a cluster is not valid. Usually
|
||||
* generated by a failed joinCluster request. */
|
||||
public static const NO_SUCH_CLUSTER :String = "m.no_such_cluster";
|
||||
|
||||
/** An error code indicating that a cluster is full. Usually generated
|
||||
* by a failed joinCluster request. */
|
||||
public static const CLUSTER_FULL :String = "m.cluster_full";
|
||||
|
||||
/** The chat type code with which we register our cluster auxiliary
|
||||
* chat objects. Chat display implementations should interpret chat
|
||||
* messages with this type accordingly. */
|
||||
public static const CLUSTER_CHAT_TYPE :String = "clusterChat";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Vilya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2012 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://code.google.com/p/vilya/
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it
|
||||
// under the terms of the GNU Lesser General Public License as published
|
||||
// by the Free Software Foundation; either version 2.1 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
package com.threerings.whirled.spot.data {
|
||||
|
||||
import com.threerings.util.Byte;
|
||||
import com.threerings.util.Integer;
|
||||
|
||||
import com.threerings.presents.client.InvocationService_ConfirmListener;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.data.InvocationMarshaller_ConfirmMarshaller;
|
||||
|
||||
import com.threerings.whirled.spot.client.SpotService;
|
||||
import com.threerings.whirled.spot.client.SpotService_SpotSceneMoveListener;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the <code>SpotService</code> interface
|
||||
* that marshalls the arguments and delivers the request to the provider
|
||||
* on the server. Also provides an implementation of the response listener
|
||||
* interfaces that marshall the response arguments and deliver them back
|
||||
* to the requesting client.
|
||||
*/
|
||||
public class SpotMarshaller extends InvocationMarshaller
|
||||
implements SpotService
|
||||
{
|
||||
/** The method id used to dispatch <code>changeLocation</code> requests. */
|
||||
public static const CHANGE_LOCATION :int = 1;
|
||||
|
||||
// from interface SpotService
|
||||
public function changeLocation (arg1 :int, arg2 :Location, arg3 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener3 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(CHANGE_LOCATION, [
|
||||
Integer.valueOf(arg1), arg2, listener3
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>clusterSpeak</code> requests. */
|
||||
public static const CLUSTER_SPEAK :int = 2;
|
||||
|
||||
// from interface SpotService
|
||||
public function clusterSpeak (arg1 :String, arg2 :int) :void
|
||||
{
|
||||
sendRequest(CLUSTER_SPEAK, [
|
||||
arg1, Byte.valueOf(arg2)
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>joinCluster</code> requests. */
|
||||
public static const JOIN_CLUSTER :int = 3;
|
||||
|
||||
// from interface SpotService
|
||||
public function joinCluster (arg1 :int, arg2 :InvocationService_ConfirmListener) :void
|
||||
{
|
||||
var listener2 :InvocationMarshaller_ConfirmMarshaller = new InvocationMarshaller_ConfirmMarshaller();
|
||||
listener2.listener = arg2;
|
||||
sendRequest(JOIN_CLUSTER, [
|
||||
Integer.valueOf(arg1), listener2
|
||||
]);
|
||||
}
|
||||
|
||||
/** The method id used to dispatch <code>traversePortal</code> requests. */
|
||||
public static const TRAVERSE_PORTAL :int = 4;
|
||||
|
||||
// from interface SpotService
|
||||
public function traversePortal (arg1 :int, arg2 :int, arg3 :int, arg4 :SpotService_SpotSceneMoveListener) :void
|
||||
{
|
||||
var listener4 :SpotMarshaller_SpotSceneMoveMarshaller = new SpotMarshaller_SpotSceneMoveMarshaller();
|
||||
listener4.listener = arg4;
|
||||
sendRequest(TRAVERSE_PORTAL, [
|
||||
Integer.valueOf(arg1), Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user