Behold Vilya, Ring of Air and repository for our game and virtual worldly
extensions to the distributed environment provided by Narya. git-svn-id: svn+ssh://src.earth.threerings.net/vilya/trunk@1 c613c5cb-e716-0410-b11b-feb51c14d237
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// $Id: Log.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* A placeholder class that contains a reference to the log object used by
|
||||
* the Parlor services.
|
||||
*/
|
||||
public class Log
|
||||
{
|
||||
public static com.samskivert.util.Log log =
|
||||
new com.samskivert.util.Log("parlor");
|
||||
|
||||
/** Convenience function. */
|
||||
public static void debug (String message)
|
||||
{
|
||||
log.debug(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void info (String message)
|
||||
{
|
||||
log.info(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void warning (String message)
|
||||
{
|
||||
log.warning(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void logStackTrace (Throwable t)
|
||||
{
|
||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// $Id: Log.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* A placeholder class that contains a reference to the log object used by
|
||||
* the Card services.
|
||||
*/
|
||||
public class Log
|
||||
{
|
||||
public static com.samskivert.util.Log log =
|
||||
new com.samskivert.util.Log("card");
|
||||
|
||||
/** Convenience function. */
|
||||
public static void debug (String message)
|
||||
{
|
||||
log.debug(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void info (String message)
|
||||
{
|
||||
log.info(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void warning (String message)
|
||||
{
|
||||
log.warning(message);
|
||||
}
|
||||
|
||||
/** Convenience function. */
|
||||
public static void logStackTrace (Throwable t)
|
||||
{
|
||||
log.logStackTrace(com.samskivert.util.Log.WARNING, t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// $Id: CardGameController.java 4053 2006-04-25 00:49:58Z mthomas $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.parlor.card.Log;
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.CardCodes;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.parlor.game.client.GameController;
|
||||
import com.threerings.parlor.turn.client.TurnGameController;
|
||||
|
||||
/**
|
||||
* A controller class for card games. Handles common functions like
|
||||
* accepting dealt hands.
|
||||
*/
|
||||
public abstract class CardGameController extends GameController
|
||||
implements TurnGameController, CardCodes, CardGameReceiver
|
||||
{
|
||||
// Documentation inherited.
|
||||
public void willEnterPlace (PlaceObject plobj)
|
||||
{
|
||||
super.willEnterPlace(plobj);
|
||||
|
||||
if (_ctx.getClient().getClientObject().receivers.containsKey(
|
||||
CardGameDecoder.RECEIVER_CODE)) {
|
||||
Log.warning("Yuh oh, we already have a card game receiver " +
|
||||
"registered and are trying for another...!");
|
||||
Thread.dumpStack();
|
||||
}
|
||||
|
||||
_ctx.getClient().getInvocationDirector().registerReceiver(
|
||||
new CardGameDecoder(this));
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void didLeavePlace (PlaceObject plobj)
|
||||
{
|
||||
super.didLeavePlace(plobj);
|
||||
|
||||
_ctx.getClient().getInvocationDirector().unregisterReceiver(
|
||||
CardGameDecoder.RECEIVER_CODE);
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void turnDidChange (Name turnHolder)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Called by our sender to notify us of a received hand.
|
||||
*/
|
||||
public final void receivedHand (int oid, Hand hand)
|
||||
{
|
||||
if (oid == _gobj.getOid()) {
|
||||
receivedHand(hand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the server deals the client a new hand of cards. Default
|
||||
* implementation does nothing.
|
||||
*
|
||||
* @param hand the hand dealt to the user
|
||||
*/
|
||||
public void receivedHand (Hand hand)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Dispatched to the client when it has received a set of cards
|
||||
* from another player. Default implementation does nothing.
|
||||
*
|
||||
* @param plidx the index of the player providing the cards
|
||||
* @param cards the cards received
|
||||
*/
|
||||
public void receivedCardsFromPlayer (int plidx, Card[] cards)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Dispatched to the client when the server has forced it to send
|
||||
* a set of cards to another player. Default implementation does
|
||||
* nothing.
|
||||
*
|
||||
* @param plidx the index of the player to which the cards were sent
|
||||
* @param cards the cards sent
|
||||
*/
|
||||
public void sentCardsToPlayer (int plidx, Card[] cards)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Dispatched to the client when a set of cards is transferred between
|
||||
* two other players in the game. Default implementation does nothing.
|
||||
*
|
||||
* @param fromidx the index of the player sending the cards
|
||||
* @param toidx the index of the player receiving the cards
|
||||
* @param cards the number of cards transferred
|
||||
*/
|
||||
public void cardsTransferredBetweenPlayers (int fromidx, int toidx,
|
||||
int cards)
|
||||
{}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client;
|
||||
|
||||
import com.threerings.parlor.card.client.CardGameReceiver;
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link CardGameReceiver} instance.
|
||||
*/
|
||||
public class CardGameDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static final String RECEIVER_CODE = "0718199d459e31d8d673744c71b0e788";
|
||||
|
||||
/** The method id used to dispatch {@link CardGameReceiver#cardsTransferredBetweenPlayers}
|
||||
* notifications. */
|
||||
public static final int CARDS_TRANSFERRED_BETWEEN_PLAYERS = 1;
|
||||
|
||||
/** The method id used to dispatch {@link CardGameReceiver#receivedCardsFromPlayer}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_CARDS_FROM_PLAYER = 2;
|
||||
|
||||
/** The method id used to dispatch {@link CardGameReceiver#receivedHand}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_HAND = 3;
|
||||
|
||||
/** The method id used to dispatch {@link CardGameReceiver#sentCardsToPlayer}
|
||||
* notifications. */
|
||||
public static final int SENT_CARDS_TO_PLAYER = 4;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public CardGameDecoder (CardGameReceiver receiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public String getReceiverCode ()
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchNotification (int methodId, Object[] args)
|
||||
{
|
||||
switch (methodId) {
|
||||
case CARDS_TRANSFERRED_BETWEEN_PLAYERS:
|
||||
((CardGameReceiver)receiver).cardsTransferredBetweenPlayers(
|
||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), ((Integer)args[2]).intValue()
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_CARDS_FROM_PLAYER:
|
||||
((CardGameReceiver)receiver).receivedCardsFromPlayer(
|
||||
((Integer)args[0]).intValue(), (Card[])args[1]
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_HAND:
|
||||
((CardGameReceiver)receiver).receivedHand(
|
||||
((Integer)args[0]).intValue(), (Hand)args[1]
|
||||
);
|
||||
return;
|
||||
|
||||
case SENT_CARDS_TO_PLAYER:
|
||||
((CardGameReceiver)receiver).sentCardsToPlayer(
|
||||
((Integer)args[0]).intValue(), (Card[])args[1]
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// $Id: ParlorReceiver.java 3099 2004-08-27 02:21:06Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
|
||||
import com.threerings.presents.client.InvocationReceiver;
|
||||
|
||||
/**
|
||||
* Defines, for the card game services, a set of notifications delivered
|
||||
* asynchronously by the server to the client.
|
||||
*/
|
||||
public interface CardGameReceiver extends InvocationReceiver
|
||||
{
|
||||
/**
|
||||
* Dispatched to the client when it has received a hand of cards.
|
||||
*
|
||||
* @param oid the oid of the game for which this hand applies
|
||||
* @param hand the received hand
|
||||
*/
|
||||
public void receivedHand (int oid, Hand hand);
|
||||
|
||||
/**
|
||||
* Dispatched to the client when it has received a set of cards
|
||||
* from another player.
|
||||
*
|
||||
* @param plidx the index of the player providing the cards
|
||||
* @param cards the cards received
|
||||
*/
|
||||
public void receivedCardsFromPlayer (int plidx, Card[] cards);
|
||||
|
||||
/**
|
||||
* Dispatched to the client when the server has forced it to send
|
||||
* a set of cards to another player.
|
||||
*
|
||||
* @param plidx the index of the player to which the cards were sent
|
||||
* @param cards the cards sent
|
||||
*/
|
||||
public void sentCardsToPlayer (int plidx, Card[] cards);
|
||||
|
||||
/**
|
||||
* Dispatched to the client when a set of cards is transferred between
|
||||
* two other players in the game.
|
||||
*
|
||||
* @param fromidx the index of the player sending the cards
|
||||
* @param toidx the index of the player receiving the cards
|
||||
* @param cards the number of cards transferred
|
||||
*/
|
||||
public void cardsTransferredBetweenPlayers (int fromidx, int toidx,
|
||||
int cards);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,252 @@
|
||||
//
|
||||
// $Id: CardSprite.java 3819 2006-01-24 19:46:34Z mthomas $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import com.threerings.media.image.Mirage;
|
||||
import com.threerings.media.sprite.FadableImageSprite;
|
||||
import com.threerings.media.util.Path;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
|
||||
/**
|
||||
* A sprite representing a playing card.
|
||||
*/
|
||||
public class CardSprite extends FadableImageSprite
|
||||
implements Comparable
|
||||
{
|
||||
/**
|
||||
* Creates a new upward-facing card sprite.
|
||||
*
|
||||
* @param panel the panel responsible for the sprite
|
||||
* @param card the card to depict (can be null, in which case the
|
||||
* card back will be shown)
|
||||
*/
|
||||
public CardSprite (CardPanel panel, Card card)
|
||||
{
|
||||
_panel = panel;
|
||||
_card = card;
|
||||
_facingUp = true;
|
||||
|
||||
updateMirage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new card sprite.
|
||||
*
|
||||
* @param panel the panel responsible for the sprite
|
||||
* @param card the card to depict
|
||||
* @param facingUp whether or not the card should be facing up
|
||||
*/
|
||||
public CardSprite (CardPanel panel, Card card, boolean facingUp)
|
||||
{
|
||||
_panel = panel;
|
||||
_card = card;
|
||||
_facingUp = facingUp;
|
||||
|
||||
updateMirage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the card to depict.
|
||||
*
|
||||
* @param card the new card
|
||||
*/
|
||||
public void setCard (Card card)
|
||||
{
|
||||
_card = card;
|
||||
|
||||
updateMirage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the card being depicted.
|
||||
*
|
||||
* @return the current card
|
||||
*/
|
||||
public Card getCard ()
|
||||
{
|
||||
return _card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns this card up or down.
|
||||
*
|
||||
* @param facingUp whether or not the card should be facing up
|
||||
*/
|
||||
public void setFacingUp (boolean facingUp)
|
||||
{
|
||||
_facingUp = facingUp;
|
||||
|
||||
updateMirage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this card is facing up or down.
|
||||
*
|
||||
* @return true if the card is facing up, false if facing down
|
||||
*/
|
||||
public boolean isFacingUp ()
|
||||
{
|
||||
return _facingUp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the user can drag this card around the board.
|
||||
*
|
||||
* @param draggable whether or not the user can drag the card
|
||||
*/
|
||||
public void setDraggable (boolean draggable)
|
||||
{
|
||||
_draggable = draggable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether or not the user can drag this card.
|
||||
*
|
||||
* @return true if the user can drag the card, false if not
|
||||
*/
|
||||
public boolean isDraggable ()
|
||||
{
|
||||
return _draggable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flip the card from its current displayed card to the specified card.
|
||||
*/
|
||||
public void flip (Card newCard, long duration)
|
||||
{
|
||||
_flipStamp = 0;
|
||||
_flipDuration = duration;
|
||||
_flipCard = newCard;
|
||||
|
||||
_scaleFactor = 1.0;
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void tick (long tickStamp)
|
||||
{
|
||||
super.tick(tickStamp);
|
||||
|
||||
// Take care of any flipping we might be doing.
|
||||
if (_flipDuration != -1) {
|
||||
if (_flipStamp == 0) {
|
||||
_flipStamp = tickStamp;
|
||||
}
|
||||
|
||||
long diff = tickStamp - _flipStamp;
|
||||
|
||||
// Set the new scale while we're flipping
|
||||
if (diff < _flipDuration/2) {
|
||||
_scaleFactor = 1.0 - ((float)diff*2)/_flipDuration;
|
||||
} else {
|
||||
// Switch the image to the card we're flipping to.
|
||||
if (_flipCard != null) {
|
||||
setCard(_flipCard);
|
||||
_flipCard = null;
|
||||
}
|
||||
_scaleFactor = ((float)diff*2)/_flipDuration - 1.0;
|
||||
}
|
||||
|
||||
// If we're done, stop flipping.
|
||||
if (_scaleFactor > 1.0) {
|
||||
_scaleFactor = 1.0;
|
||||
_flipDuration = -1;
|
||||
}
|
||||
|
||||
// Make sure we flag our location as needing redrawing
|
||||
if (_mgr != null) {
|
||||
_mgr.getRegionManager().invalidateRegion(_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void paint (Graphics2D gfx)
|
||||
{
|
||||
if (_scaleFactor <= 0) {
|
||||
return;
|
||||
}
|
||||
// If we are flipping the card, scale it horizontally.
|
||||
AffineTransform otrans = gfx.getTransform();
|
||||
if (_scaleFactor < 1.0) {
|
||||
int xtrans = getX() + getWidth()/2;
|
||||
gfx.translate(xtrans, 0);
|
||||
gfx.scale(_scaleFactor, 1.0);
|
||||
gfx.translate(-xtrans, 0);
|
||||
}
|
||||
|
||||
super.paint(gfx);
|
||||
|
||||
gfx.setTransform(otrans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this to another card sprite based on their cards.
|
||||
*/
|
||||
public int compareTo (Object other)
|
||||
{
|
||||
CardSprite cs = (CardSprite)other;
|
||||
if (_card == null || cs._card == null) {
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
return _card.compareTo(cs._card);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the mirage according to the current state.
|
||||
*/
|
||||
protected void updateMirage ()
|
||||
{
|
||||
setMirage((_card != null && _facingUp ) ?
|
||||
_panel.getCardImage(_card) : _panel.getCardBackImage());
|
||||
}
|
||||
|
||||
/** The panel responsible for the sprite. */
|
||||
protected CardPanel _panel;
|
||||
|
||||
/** The depicted card. */
|
||||
protected Card _card;
|
||||
|
||||
/** Whether or not the card is facing up. */
|
||||
protected boolean _facingUp;
|
||||
|
||||
/** Whether or not the user can drag the card around the board. */
|
||||
protected boolean _draggable;
|
||||
|
||||
/** The horizontal scale factor used while flipping the card. */
|
||||
protected double _scaleFactor = 1.0;
|
||||
|
||||
/** If flipping, how long the current flip should take (otherwise -1). */
|
||||
protected long _flipDuration;
|
||||
|
||||
/** The timestamp for when we started flipping the card. */
|
||||
protected long _flipStamp;
|
||||
|
||||
/** The card which will be revealed when we're done flipping. */
|
||||
protected Card _flipCard;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// $Id: CardSpriteObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* Observer interface for (draggable) card sprites.
|
||||
*/
|
||||
public interface CardSpriteObserver
|
||||
{
|
||||
/**
|
||||
* Notifies the observer that the user clicked a card sprite.
|
||||
*
|
||||
* @param sprite the dragged sprite
|
||||
* @param me the mouse event associated with the drag
|
||||
*/
|
||||
public void cardSpriteClicked (CardSprite sprite, MouseEvent me);
|
||||
|
||||
/**
|
||||
* Notifies the observer that the user moved the mouse pointer onto
|
||||
* a card sprite.
|
||||
*
|
||||
* @param sprite the entered sprite
|
||||
* @param me the mouse event associated with the entrance
|
||||
*/
|
||||
public void cardSpriteEntered (CardSprite sprite, MouseEvent me);
|
||||
|
||||
/**
|
||||
* Notifies the observer that the user moved the mouse pointer off of
|
||||
* a card sprite.
|
||||
*
|
||||
* @param sprite the exited the sprite
|
||||
* @param me the mouse event associated with the exit
|
||||
*/
|
||||
public void cardSpriteExited (CardSprite sprite, MouseEvent me);
|
||||
|
||||
/**
|
||||
* Notifies the observer that the user dragged a card sprite to a new
|
||||
* location.
|
||||
*
|
||||
* @param sprite the dragged sprite
|
||||
* @param me the mouse event associated with the drag
|
||||
*/
|
||||
public void cardSpriteDragged (CardSprite sprite, MouseEvent me);
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
|
||||
public class MicroCardSprite extends CardSprite
|
||||
{
|
||||
/**
|
||||
* Creates a new upward-facing micro-card sprite.
|
||||
*
|
||||
* @param panel the panel responsible for the sprite
|
||||
* @param card the card to depict (can be null, in which case the
|
||||
* card back will be shown)
|
||||
*/
|
||||
public MicroCardSprite (CardPanel panel, Card card)
|
||||
{
|
||||
super(panel, card);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new micro-card sprite.
|
||||
*
|
||||
* @param panel the panel responsible for the sprite
|
||||
* @param card the card to depict
|
||||
* @param facingUp whether or not the card should be facing up
|
||||
*/
|
||||
public MicroCardSprite (CardPanel panel, Card card, boolean facingUp)
|
||||
{
|
||||
super(panel, card, facingUp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the mirage according to the current state.
|
||||
*/
|
||||
protected void updateMirage ()
|
||||
{
|
||||
setMirage((_card != null && _facingUp ) ?
|
||||
_panel.getMicroCardImage(_card) : _panel.getMicroCardBackImage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
//
|
||||
// $Id: Card.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.io.IOException;
|
||||
|
||||
import com.threerings.io.ObjectInputStream;
|
||||
import com.threerings.io.ObjectOutputStream;
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
|
||||
/**
|
||||
* Instances of this class represent individual playing cards.
|
||||
*/
|
||||
public class Card implements DSet.Entry, Comparable, CardCodes
|
||||
{
|
||||
/**
|
||||
* No-arg constructor for deserialization.
|
||||
*/
|
||||
public Card ()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Creates a new card.
|
||||
*
|
||||
* @param number the number of the card
|
||||
* @param suit the suit of the card
|
||||
*/
|
||||
public Card (int number, int suit)
|
||||
{
|
||||
_value = (byte)((suit << 5) | number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 int getNumber ()
|
||||
{
|
||||
return (_value & 0x1F);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 int getSuit ()
|
||||
{
|
||||
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 boolean isNumber ()
|
||||
{
|
||||
int number = 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 boolean isFace ()
|
||||
{
|
||||
int number = getNumber();
|
||||
|
||||
return number == KING || number == QUEEN || number == JACK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the card is an ace.
|
||||
*
|
||||
* @return true if the card is an ace, false otherwise
|
||||
*/
|
||||
public boolean isAce ()
|
||||
{
|
||||
return getNumber() == ACE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the card is a joker.
|
||||
*
|
||||
* @return true if the card is a joker, false otherwise
|
||||
*/
|
||||
public boolean isJoker ()
|
||||
{
|
||||
int number = getNumber();
|
||||
|
||||
return number == RED_JOKER || number == BLACK_JOKER;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 boolean isValid ()
|
||||
{
|
||||
int number = getNumber(), suit = getSuit();
|
||||
|
||||
return number == RED_JOKER || number == BLACK_JOKER ||
|
||||
(number >= 2 && number <= ACE &&
|
||||
suit >= SPADES && suit <= DIAMONDS);
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public Comparable getKey ()
|
||||
{
|
||||
if (_key == null) {
|
||||
_key = Byte.valueOf(_value);
|
||||
}
|
||||
|
||||
return _key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for this card.
|
||||
*
|
||||
* @return this card's hash code
|
||||
*/
|
||||
public int hashCode ()
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks this card for equality with another.
|
||||
*
|
||||
* @param other the other card to compare
|
||||
* @return true if the cards are equal, false otherwise
|
||||
*/
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
if (other instanceof Card) {
|
||||
return _value == ((Card)other)._value;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 int compareTo (Object other)
|
||||
{
|
||||
int otherValue = ((Card)other)._value;
|
||||
|
||||
if (_value > otherValue) {
|
||||
return +1;
|
||||
} else if(_value < otherValue) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this card.
|
||||
*
|
||||
* @return a description of this card
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
int number = getNumber();
|
||||
|
||||
if (number == RED_JOKER) {
|
||||
return "RJ";
|
||||
}
|
||||
else if (number == BLACK_JOKER) {
|
||||
return "BJ";
|
||||
}
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if (number >= 2 && number <= 9) {
|
||||
sb.append(Integer.toString(number));
|
||||
}
|
||||
else {
|
||||
switch (number) {
|
||||
case 10: sb.append('T'); break;
|
||||
case JACK: sb.append('J'); break;
|
||||
case QUEEN: sb.append('Q'); break;
|
||||
case KING: sb.append('K'); break;
|
||||
case ACE: sb.append('A'); break;
|
||||
default: sb.append('?'); break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (getSuit()) {
|
||||
case SPADES: sb.append('s'); break;
|
||||
case HEARTS: sb.append('h'); break;
|
||||
case CLUBS: sb.append('c'); break;
|
||||
case DIAMONDS: sb.append('d'); break;
|
||||
default: sb.append('?'); break;
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
/** The number of the card. */
|
||||
protected byte _value;
|
||||
|
||||
/** The comparison key. */
|
||||
protected transient Byte _key;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// $Id: CardCodes.java 3224 2004-11-19 19:04:56Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.presents.data.InvocationCodes;
|
||||
|
||||
/**
|
||||
* Constants relating to the card services.
|
||||
*/
|
||||
public interface CardCodes extends InvocationCodes
|
||||
{
|
||||
/** The suit of spades. */
|
||||
public static final int SPADES = 0;
|
||||
|
||||
/** The suit of hearts. */
|
||||
public static final int HEARTS = 1;
|
||||
|
||||
/** The suit of clubs. */
|
||||
public static final int CLUBS = 2;
|
||||
|
||||
/** The suit of diamonds. */
|
||||
public static final int DIAMONDS = 3;
|
||||
|
||||
/** The number of the jack. */
|
||||
public static final int JACK = 11;
|
||||
|
||||
/** The number of the queen. */
|
||||
public static final int QUEEN = 12;
|
||||
|
||||
/** The number of the king. */
|
||||
public static final int KING = 13;
|
||||
|
||||
/** The number of the ace. */
|
||||
public static final int ACE = 14;
|
||||
|
||||
/** The number of the red joker. */
|
||||
public static final int RED_JOKER = 15;
|
||||
|
||||
/** The number of the black joker. */
|
||||
public static final int BLACK_JOKER = 16;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// $Id: TurnGameObject.java 3099 2004-08-27 02:21:06Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.game.data.GameObject;
|
||||
|
||||
/**
|
||||
* Game object class for card games.
|
||||
*/
|
||||
public class CardGameObject extends GameObject
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// $Id: Deck.java 3713 2005-09-27 21:58:10Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.threerings.util.StreamableArrayList;
|
||||
|
||||
/**
|
||||
* Instances of this class represent decks of cards.
|
||||
*/
|
||||
public class Deck extends StreamableArrayList
|
||||
implements CardCodes
|
||||
{
|
||||
/**
|
||||
* Default constructor creates an unshuffled deck of cards without
|
||||
* jokers.
|
||||
*/
|
||||
public Deck ()
|
||||
{
|
||||
reset(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param includeJokers whether or not to include the two jokers
|
||||
* in the deck
|
||||
*/
|
||||
public Deck (boolean includeJokers)
|
||||
{
|
||||
reset(includeJokers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void reset (boolean includeJokers)
|
||||
{
|
||||
clear();
|
||||
|
||||
for (int i = SPADES; i <= DIAMONDS; i++) {
|
||||
for (int j = 2; j <= ACE; j++) {
|
||||
add(new Card(j, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (includeJokers) {
|
||||
add(new Card(RED_JOKER, 3));
|
||||
add(new Card(BLACK_JOKER, 3));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffles the deck.
|
||||
*/
|
||||
public void shuffle ()
|
||||
{
|
||||
Collections.shuffle(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Hand dealHand (int size)
|
||||
{
|
||||
int dsize = size();
|
||||
if (dsize < size) {
|
||||
return null;
|
||||
|
||||
} else {
|
||||
Hand hand = new Hand();
|
||||
|
||||
// use a sublist view to manipulate the top of the deck
|
||||
List sublist = subList(dsize - size, dsize);
|
||||
hand.addAll(sublist);
|
||||
sublist.clear();
|
||||
|
||||
return hand;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hand of cards to the deck.
|
||||
*
|
||||
* @param hand the hand of cards to return
|
||||
*/
|
||||
public void returnHand (Hand hand)
|
||||
{
|
||||
addAll(hand);
|
||||
hand.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
//
|
||||
// $Id: Hand.java 3813 2006-01-19 21:50:53Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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
|
||||
{
|
||||
/**
|
||||
* Adds all of the specified cards to this hand.
|
||||
*/
|
||||
public void addAll (Card[] cards)
|
||||
{
|
||||
for (int i = 0; i < cards.length; i++) {
|
||||
add(cards[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the specified cards from this hand.
|
||||
*/
|
||||
public void removeAll (Card[] cards)
|
||||
{
|
||||
for (int i = 0; i < cards.length; i++) {
|
||||
remove(cards[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this hand contains all of the specified cards.
|
||||
*/
|
||||
public boolean containsAll (Card[] cards)
|
||||
{
|
||||
for (int i = 0; i < cards.length; i++) {
|
||||
if (!contains(cards[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 int getSuitMemberCount (int suit)
|
||||
{
|
||||
int len = size(), members = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (((Card)get(i)).getSuit() == suit) {
|
||||
members++;
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of the cards in this hand.
|
||||
*/
|
||||
public Card[] getCards ()
|
||||
{
|
||||
Card[] cards = new Card[size()];
|
||||
toArray(cards);
|
||||
return cards;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// $Id: TrickCardGameObject.java 3382 2005-03-03 19:55:35Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.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 int pidx;
|
||||
|
||||
/** The card that the player played. */
|
||||
public Card card;
|
||||
|
||||
/**
|
||||
* No-argument constructor for deserialization.
|
||||
*/
|
||||
public PlayerCard ()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Creates a new player card.
|
||||
*
|
||||
* @param pidx the index of the player
|
||||
* @param card the card played
|
||||
*/
|
||||
public PlayerCard (int pidx, Card card)
|
||||
{
|
||||
this.pidx = pidx;
|
||||
this.card = card;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
//
|
||||
// $Id: CardGameManager.java 3829 2006-02-03 19:11:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.OccupantInfo;
|
||||
import com.threerings.crowd.server.OccupantOp;
|
||||
|
||||
import com.threerings.parlor.card.Log;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.CardCodes;
|
||||
import com.threerings.parlor.card.data.CardGameObject;
|
||||
import com.threerings.parlor.card.data.Deck;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
import com.threerings.parlor.turn.server.TurnGameManager;
|
||||
|
||||
import com.threerings.presents.client.InvocationService.ConfirmListener;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.dobj.MessageEvent;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.PresentsServer;
|
||||
|
||||
/**
|
||||
* A manager class for card games. Handles common functions like dealing
|
||||
* hands of cards to all players.
|
||||
*/
|
||||
public class CardGameManager extends GameManager
|
||||
implements TurnGameManager, CardCodes
|
||||
{
|
||||
// Documentation inherited.
|
||||
protected void didStartup ()
|
||||
{
|
||||
super.didStartup();
|
||||
_cardgameobj = (CardGameObject)_gameobj;
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void turnWillStart ()
|
||||
{}
|
||||
|
||||
// Documentation inherited.
|
||||
public void turnDidStart ()
|
||||
{}
|
||||
|
||||
// Documentation inherited.
|
||||
public void turnDidEnd ()
|
||||
{}
|
||||
|
||||
/**
|
||||
* This should be called to start a rematched game. It just starts the
|
||||
* current game anew, but provides a mechanism for derived classes to
|
||||
* do special things when there is a rematch.
|
||||
*/
|
||||
public void rematchGame ()
|
||||
{
|
||||
if (gameWillRematch()) {
|
||||
startGame();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes can override this method and take any action needed
|
||||
* prior to a game rematch. If the rematch needs to be vetoed for any
|
||||
* reason, they can return false from this method and the rematch will
|
||||
* be aborted.
|
||||
*/
|
||||
protected boolean gameWillRematch ()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deals a hand of cards to the player at the specified index from
|
||||
* the given Deck.
|
||||
*
|
||||
* @param deck the deck from which to deal
|
||||
* @param size the size of the hand to deal
|
||||
* @param playerIndex the index of the target player
|
||||
* @return the hand dealt to the player, or null if the deal
|
||||
* was canceled because the deck did not contain enough cards
|
||||
*/
|
||||
public Hand dealHand (Deck deck, int size, int playerIndex)
|
||||
{
|
||||
if (deck.size() < size) {
|
||||
return null;
|
||||
|
||||
} else {
|
||||
Hand hand = deck.dealHand(size);
|
||||
if (!isAI(playerIndex)) {
|
||||
ClientObject clobj = (ClientObject)
|
||||
PresentsServer.omgr.getObject(_playerOids[playerIndex]);
|
||||
if (clobj != null) {
|
||||
CardGameSender.sendHand(clobj, _cardgameobj.getOid(), hand);
|
||||
}
|
||||
}
|
||||
return hand;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deals a hand of cards to each player from the specified
|
||||
* Deck.
|
||||
*
|
||||
* @param deck the deck from which to deal
|
||||
* @param size the size of the hands to deal
|
||||
* @return the array of hands dealt to each player, or null if
|
||||
* the deal was canceled because the deck did not contain enough
|
||||
* cards
|
||||
*/
|
||||
public Hand[] dealHands (Deck deck, int size)
|
||||
{
|
||||
if (deck.size() < size * _playerCount) {
|
||||
return null;
|
||||
|
||||
} else {
|
||||
Hand[] hands = new Hand[_playerCount];
|
||||
|
||||
for (int i=0;i<_playerCount;i++) {
|
||||
hands[i] = dealHand(deck, size, i);
|
||||
}
|
||||
|
||||
return hands;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player index of the specified client object, or -1
|
||||
* if the client object does not represent a player.
|
||||
*/
|
||||
public int getPlayerIndex (ClientObject client)
|
||||
{
|
||||
int oid = client.getOid();
|
||||
for (int i=0;i<_playerOids.length;i++) {
|
||||
if (_playerOids[i] == oid) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client object corresponding to the specified player index,
|
||||
* or null if the position is not occupied by a player.
|
||||
*/
|
||||
public ClientObject getClientObject (int pidx)
|
||||
{
|
||||
if (_playerOids[pidx] != 0) {
|
||||
return (ClientObject)PresentsServer.omgr.getObject(
|
||||
_playerOids[pidx]);
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a set of cards from one player to another.
|
||||
*
|
||||
* @param fromPlayerIdx the index of the player sending the cards
|
||||
* @param toPlayerIdx the index of the player receiving the cards
|
||||
* @param cards the cards to be exchanged
|
||||
*/
|
||||
public void transferCardsBetweenPlayers (int fromPlayerIdx,
|
||||
int toPlayerIdx, Card[] cards)
|
||||
{
|
||||
// Notify the sender that the cards have been taken
|
||||
ClientObject fromClient = getClientObject(fromPlayerIdx);
|
||||
if (fromClient != null) {
|
||||
CardGameSender.sentCardsToPlayer(fromClient, toPlayerIdx, cards);
|
||||
}
|
||||
|
||||
// Notify the receiver with the cards
|
||||
ClientObject toClient = getClientObject(toPlayerIdx);
|
||||
if (toClient != null) {
|
||||
CardGameSender.sendCardsFromPlayer(toClient, fromPlayerIdx,
|
||||
cards);
|
||||
}
|
||||
|
||||
// and everybody else in the room other than the sender and the
|
||||
// receiver with the number of cards sent
|
||||
notifyCardsTransferred(fromPlayerIdx, toPlayerIdx, cards.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends sets of cards between players simultaneously. Each player is
|
||||
* guaranteed to receive the notification of cards received after the
|
||||
* notification of cards sent. The length of the arrays passed must
|
||||
* be equal to the player count.
|
||||
*
|
||||
* @param toPlayerIndices for each player, the index of the player to
|
||||
* transfer cards to
|
||||
* @param cards for each player, the cards to transfer
|
||||
*/
|
||||
public void transferCardsBetweenPlayers (int[] toPlayerIndices,
|
||||
Card[][] cards)
|
||||
{
|
||||
// Send all removal notices
|
||||
for (int i = 0; i < _playerCount; i++) {
|
||||
ClientObject fromClient = getClientObject(i);
|
||||
if (fromClient != null) {
|
||||
CardGameSender.sentCardsToPlayer(fromClient,
|
||||
toPlayerIndices[i], cards[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Send all addition notices and notify everyone else
|
||||
for (int i = 0; i < _playerCount; i++) {
|
||||
ClientObject toClient = getClientObject(toPlayerIndices[i]);
|
||||
if (toClient != null) {
|
||||
CardGameSender.sendCardsFromPlayer(toClient, i, cards[i]);
|
||||
}
|
||||
notifyCardsTransferred(i, toPlayerIndices[i], cards[i].length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies everyone in the room (other than the sender and the receiver)
|
||||
* that a set of cards have been transferred.
|
||||
*
|
||||
* @param fromPlayerIdx the index of the player sending the cards
|
||||
* @param toPlayerIdx the index of the player receiving the cards
|
||||
* @param cards the number of cards sent
|
||||
*/
|
||||
protected void notifyCardsTransferred (final int fromPlayerIdx,
|
||||
final int toPlayerIdx, final int cards)
|
||||
{
|
||||
final int senderOid = _playerOids[fromPlayerIdx],
|
||||
receiverOid = _playerOids[toPlayerIdx];
|
||||
OccupantOp op = new OccupantOp() {
|
||||
public void apply (OccupantInfo info) {
|
||||
int oid = info.getBodyOid();
|
||||
if (oid != senderOid && oid != receiverOid) {
|
||||
ClientObject client =
|
||||
(ClientObject)PresentsServer.omgr.getObject(oid);
|
||||
if (client != null) {
|
||||
CardGameSender.cardsTransferredBetweenPlayers(client,
|
||||
fromPlayerIdx, toPlayerIdx, cards);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
applyToOccupants(op);
|
||||
}
|
||||
|
||||
/** The card game object. */
|
||||
protected CardGameObject _cardgameobj;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.card.client.CardGameDecoder;
|
||||
import com.threerings.parlor.card.client.CardGameReceiver;
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.server.InvocationSender;
|
||||
|
||||
/**
|
||||
* Used to issue notifications to a {@link CardGameReceiver} instance on a
|
||||
* client.
|
||||
*/
|
||||
public class CardGameSender extends InvocationSender
|
||||
{
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* CardGameReceiver#cardsTransferredBetweenPlayers} on a client.
|
||||
*/
|
||||
public static void cardsTransferredBetweenPlayers (
|
||||
ClientObject target, int arg1, int arg2, int arg3)
|
||||
{
|
||||
sendNotification(
|
||||
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.CARDS_TRANSFERRED_BETWEEN_PLAYERS,
|
||||
new Object[] { Integer.valueOf(arg1), Integer.valueOf(arg2), Integer.valueOf(arg3) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* CardGameReceiver#receivedCardsFromPlayer} on a client.
|
||||
*/
|
||||
public static void sendCardsFromPlayer (
|
||||
ClientObject target, int arg1, Card[] arg2)
|
||||
{
|
||||
sendNotification(
|
||||
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.RECEIVED_CARDS_FROM_PLAYER,
|
||||
new Object[] { Integer.valueOf(arg1), arg2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* CardGameReceiver#receivedHand} on a client.
|
||||
*/
|
||||
public static void sendHand (
|
||||
ClientObject target, int arg1, Hand arg2)
|
||||
{
|
||||
sendNotification(
|
||||
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.RECEIVED_HAND,
|
||||
new Object[] { Integer.valueOf(arg1), arg2 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* CardGameReceiver#sentCardsToPlayer} on a client.
|
||||
*/
|
||||
public static void sentCardsToPlayer (
|
||||
ClientObject target, int arg1, Card[] arg2)
|
||||
{
|
||||
sendNotification(
|
||||
target, CardGameDecoder.RECEIVER_CODE, CardGameDecoder.SENT_CARDS_TO_PLAYER,
|
||||
new Object[] { Integer.valueOf(arg1), arg2 });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// $Id: TrickCardGameControllerDelegate.java 3465 2005-04-12 02:50:17Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.turn.client.TurnGameControllerDelegate;
|
||||
|
||||
import com.threerings.parlor.card.client.CardGameController;
|
||||
|
||||
/**
|
||||
* A card game controller delegate for trick-based card games, such as
|
||||
* Spades and Hearts.
|
||||
*/
|
||||
public class TrickCardGameControllerDelegate
|
||||
extends TurnGameControllerDelegate
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param controller the game controller
|
||||
*/
|
||||
public TrickCardGameControllerDelegate (CardGameController
|
||||
controller)
|
||||
{
|
||||
super(controller);
|
||||
_cgctrl = controller;
|
||||
}
|
||||
|
||||
/** The card game controller. */
|
||||
protected CardGameController _cgctrl;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//
|
||||
// $Id: RoisterService.java 17829 2004-11-12 20:24:43Z mdb $
|
||||
|
||||
package com.threerings.parlor.card.trick.client;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
/**
|
||||
* Service calls related to trick card games.
|
||||
*/
|
||||
public interface TrickCardGameService extends InvocationService
|
||||
{
|
||||
/**
|
||||
* Sends a group of cards to the player at the specified index.
|
||||
*
|
||||
* @param client the client object
|
||||
* @param toidx the index of the player to send the cards to
|
||||
* @param cards the cards to send
|
||||
*/
|
||||
public void sendCardsToPlayer (Client client, int toidx, Card[] cards);
|
||||
|
||||
/**
|
||||
* Plays a card in the trick.
|
||||
*
|
||||
* @param client the client object
|
||||
* @param card the card to play
|
||||
* @param handSize the size of the player's hand, which is used to verify
|
||||
* that the request is for the current trick
|
||||
*/
|
||||
public void playCard (Client client, Card card, int handSize);
|
||||
|
||||
/**
|
||||
* A request for a rematch.
|
||||
*
|
||||
* @param client the client object
|
||||
*/
|
||||
public void requestRematch (Client client);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// $Id: CardCodes.java 3224 2004-11-19 19:04:56Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.card.data.CardCodes;
|
||||
|
||||
/**
|
||||
* Constants relating to trick-based card games.
|
||||
*/
|
||||
public interface TrickCardCodes extends CardCodes
|
||||
{
|
||||
/** For four-player games, the bottom (own) player. */
|
||||
public static final int BOTTOM = 0;
|
||||
|
||||
/** For four-player games, the player on the left. */
|
||||
public static final int LEFT = 1;
|
||||
|
||||
/** For four-player games, the top (opposite) player. */
|
||||
public static final int TOP = 2;
|
||||
|
||||
/** For four-player games, the player on the right. */
|
||||
public static final int RIGHT = 3;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the {@link TrickCardGameService} 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 {@link #playCard} requests. */
|
||||
public static final int PLAY_CARD = 1;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void playCard (Client arg1, Card arg2, int arg3)
|
||||
{
|
||||
sendRequest(arg1, PLAY_CARD, new Object[] {
|
||||
arg2, Integer.valueOf(arg3)
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #requestRematch} requests. */
|
||||
public static final int REQUEST_REMATCH = 2;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void requestRematch (Client arg1)
|
||||
{
|
||||
sendRequest(arg1, REQUEST_REMATCH, new Object[] {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #sendCardsToPlayer} requests. */
|
||||
public static final int SEND_CARDS_TO_PLAYER = 3;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void sendCardsToPlayer (Client arg1, int arg2, Card[] arg3)
|
||||
{
|
||||
sendRequest(arg1, SEND_CARDS_TO_PLAYER, new Object[] {
|
||||
Integer.valueOf(arg2), arg3
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
//
|
||||
// $Id: TrickCardGameObject.java 3516 2005-04-21 00:47:17Z andrzej $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.parlor.card.data.PlayerCard;
|
||||
import com.threerings.parlor.turn.data.TurnGameObject;
|
||||
|
||||
/**
|
||||
* Game objects for trick-based card games must implement this interface.
|
||||
*/
|
||||
public interface TrickCardGameObject extends TurnGameObject
|
||||
{
|
||||
/** The state that indicates the game is currently between hands. */
|
||||
public static final int BETWEEN_HANDS = 0;
|
||||
|
||||
/** The state that indicates the game is currently playing a hand. */
|
||||
public static final int PLAYING_HAND = 1;
|
||||
|
||||
/** The state that indicates the game is currently playing a trick. */
|
||||
public static final int PLAYING_TRICK = 2;
|
||||
|
||||
/** The number of states defined for the base trick card game object. */
|
||||
public static final int TRICK_STATE_COUNT = 3;
|
||||
|
||||
/** Indicates that the player has not requested or accepted a rematch. */
|
||||
public static final int NO_REQUEST = 0;
|
||||
|
||||
/** Indicates that the player has requested a rematch. */
|
||||
public static final int REQUESTS_REMATCH = 1;
|
||||
|
||||
/** Indicates that the player has accepted the rematch request. */
|
||||
public static final int ACCEPTS_REMATCH = 2;
|
||||
|
||||
/**
|
||||
* Returns a reference to the trick card game service used to make
|
||||
* requests to the server.
|
||||
*
|
||||
* @return a reference to the trick card game service
|
||||
*/
|
||||
public TrickCardGameMarshaller getTrickCardGameService ();
|
||||
|
||||
/**
|
||||
* Sets the reference to the trick card game service.
|
||||
*
|
||||
* @param trickCardGameService the trick card game service
|
||||
*/
|
||||
public void setTrickCardGameService (TrickCardGameMarshaller
|
||||
trickCardGameService);
|
||||
|
||||
/**
|
||||
* Returns the name of the field that contains the trick state: between
|
||||
* hands, playing a hand, or playing a trick.
|
||||
*
|
||||
* @return the name of the trickState field
|
||||
*/
|
||||
public String getTrickStateFieldName ();
|
||||
|
||||
/**
|
||||
* Returns the trick state: between hands, playing a hand, or playing a
|
||||
* trick.
|
||||
*
|
||||
* @return the trick state
|
||||
*/
|
||||
public int getTrickState ();
|
||||
|
||||
/**
|
||||
* Sets the trick state.
|
||||
*
|
||||
* @param trickState the trick state
|
||||
*/
|
||||
public void setTrickState (int trickState);
|
||||
|
||||
/**
|
||||
* Returns an array containing the turn duration scales for each player.
|
||||
* Turn duration scales decrease each time players time out.
|
||||
*
|
||||
* @return the array of turn duration scales
|
||||
*/
|
||||
public float[] getTurnDurationScales ();
|
||||
|
||||
/**
|
||||
* Sets the array of turn duration scales.
|
||||
*
|
||||
* @param turnDurationScales the array of turn duration scales
|
||||
*/
|
||||
public void setTurnDurationScales (float[] turnDurationScales);
|
||||
|
||||
/**
|
||||
* Sets an element of the array of turn duration scales.
|
||||
*
|
||||
* @param turnDurationScale the turn duration scale
|
||||
* @param index the index of the turn duration scale
|
||||
*/
|
||||
public void setTurnDurationScalesAt (float turnDurationScale, int index);
|
||||
|
||||
/**
|
||||
* Returns the duration of the current turn, which may depend on the state
|
||||
* of the game as well as the duration scale of the active player.
|
||||
*/
|
||||
public long getTurnDuration ();
|
||||
|
||||
/**
|
||||
* Returns the name of the field that contains the history of the trick
|
||||
* in terms of the cards played by each player.
|
||||
*
|
||||
* @return the name of the cardsPlayed field
|
||||
*/
|
||||
public String getCardsPlayedFieldName ();
|
||||
|
||||
/**
|
||||
* Returns an array containing the history of the trick in terms of the
|
||||
* cards played by each player.
|
||||
*
|
||||
* @return the cards played so far in the trick
|
||||
*/
|
||||
public PlayerCard[] getCardsPlayed ();
|
||||
|
||||
/**
|
||||
* Sets the array of cards played by each player.
|
||||
*
|
||||
* @param cardsPlayed the array of cards played
|
||||
*/
|
||||
public void setCardsPlayed (PlayerCard[] cardsPlayed);
|
||||
|
||||
/**
|
||||
* Returns the name of the field that contains the history of the last
|
||||
* trick in terms of the cards played by each player.
|
||||
*
|
||||
* @return the name of the lastCardsPlayed field
|
||||
*/
|
||||
public String getLastCardsPlayedFieldName ();
|
||||
|
||||
/**
|
||||
* Returns an array containing the history of the last trick in terms of
|
||||
* the cards played by each player.
|
||||
*
|
||||
* @return the cards played in the last trick
|
||||
*/
|
||||
public PlayerCard[] getLastCardsPlayed ();
|
||||
|
||||
/**
|
||||
* Sets the last array of cards played by each player.
|
||||
*
|
||||
* @param lastCardsPlayed the last array of cards played
|
||||
*/
|
||||
public void setLastCardsPlayed (PlayerCard[] lastCardsPlayed);
|
||||
|
||||
/**
|
||||
* Returns the name of the field that contains the rematch requests.
|
||||
*
|
||||
* @return the name of the rematchRequests field
|
||||
*/
|
||||
public String getRematchRequestsFieldName ();
|
||||
|
||||
/**
|
||||
* Returns the array of rematch requests.
|
||||
*
|
||||
* @return the array of rematch requests
|
||||
*/
|
||||
public int[] getRematchRequests ();
|
||||
|
||||
/**
|
||||
* Sets the array of rematch requests.
|
||||
*
|
||||
* @param rematchRequests the array of rematch requests
|
||||
*/
|
||||
public void setRematchRequests (int[] rematchRequests);
|
||||
|
||||
/**
|
||||
* Sets an element of the rematch request array.
|
||||
*
|
||||
* @param rematchRequest the rematch request value
|
||||
* @param index the index at which to set the value
|
||||
*/
|
||||
public void setRematchRequestsAt (int rematchRequest, int index);
|
||||
|
||||
/**
|
||||
* Checks whether a user can play the specified card at this time.
|
||||
*
|
||||
* @param hand the player's hand
|
||||
* @param card the card that the user would like to play
|
||||
*/
|
||||
public boolean isCardPlayable (Hand hand, Card card);
|
||||
|
||||
/**
|
||||
* Returns the card of the player who took the current trick.
|
||||
*/
|
||||
public PlayerCard getTrickTaker ();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||
import com.threerings.parlor.card.trick.data.TrickCardGameMarshaller;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.server.InvocationDispatcher;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
|
||||
/**
|
||||
* Dispatches requests to the {@link TrickCardGameProvider}.
|
||||
*/
|
||||
public class TrickCardGameDispatcher extends InvocationDispatcher
|
||||
{
|
||||
/**
|
||||
* Creates a dispatcher that may be registered to dispatch invocation
|
||||
* service requests for the specified provider.
|
||||
*/
|
||||
public TrickCardGameDispatcher (TrickCardGameProvider provider)
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public InvocationMarshaller createMarshaller ()
|
||||
{
|
||||
return new TrickCardGameMarshaller();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchRequest (
|
||||
ClientObject source, int methodId, Object[] args)
|
||||
throws InvocationException
|
||||
{
|
||||
switch (methodId) {
|
||||
case TrickCardGameMarshaller.PLAY_CARD:
|
||||
((TrickCardGameProvider)provider).playCard(
|
||||
source,
|
||||
(Card)args[0], ((Integer)args[1]).intValue()
|
||||
);
|
||||
return;
|
||||
|
||||
case TrickCardGameMarshaller.REQUEST_REMATCH:
|
||||
((TrickCardGameProvider)provider).requestRematch(
|
||||
source
|
||||
);
|
||||
return;
|
||||
|
||||
case TrickCardGameMarshaller.SEND_CARDS_TO_PLAYER:
|
||||
((TrickCardGameProvider)provider).sendCardsToPlayer(
|
||||
source,
|
||||
((Integer)args[0]).intValue(), (Card[])args[1]
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchRequest(source, methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,643 @@
|
||||
//
|
||||
// $Id: TrickCardGameManagerDelegate.java 4188 2006-06-13 18:03:48Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.samskivert.util.ArrayUtil;
|
||||
import com.samskivert.util.Interval;
|
||||
import com.samskivert.util.RandomUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
import com.threerings.presents.server.PresentsServer;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
import com.threerings.parlor.turn.server.TurnGameManagerDelegate;
|
||||
|
||||
import com.threerings.parlor.card.Log;
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.CardGameObject;
|
||||
import com.threerings.parlor.card.data.Deck;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.parlor.card.data.PlayerCard;
|
||||
import com.threerings.parlor.card.server.CardGameManager;
|
||||
import com.threerings.parlor.card.trick.data.TrickCardGameMarshaller;
|
||||
import com.threerings.parlor.card.trick.data.TrickCardGameObject;
|
||||
|
||||
/**
|
||||
* A card game manager delegate for trick-based card games, such as
|
||||
* Spades and Hearts.
|
||||
*/
|
||||
public class TrickCardGameManagerDelegate extends TurnGameManagerDelegate
|
||||
implements TrickCardGameProvider
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param manager the game manager
|
||||
*/
|
||||
public TrickCardGameManagerDelegate (CardGameManager manager)
|
||||
{
|
||||
super(manager);
|
||||
|
||||
_cgmgr = manager;
|
||||
_deck = new Deck();
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void didStartup (PlaceObject plobj)
|
||||
{
|
||||
super.didStartup(plobj);
|
||||
|
||||
_trickCardGame = (TrickCardGameObject)plobj;
|
||||
|
||||
_cardGame = (CardGameObject)plobj;
|
||||
|
||||
_trickCardGame.setTrickCardGameService(
|
||||
(TrickCardGameMarshaller)PresentsServer.invmgr.registerDispatcher(
|
||||
new TrickCardGameDispatcher(this), false));
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void didShutdown ()
|
||||
{
|
||||
super.didShutdown();
|
||||
|
||||
PresentsServer.invmgr.clearDispatcher(
|
||||
_trickCardGame.getTrickCardGameService());
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void gameWillStart ()
|
||||
{
|
||||
super.gameWillStart();
|
||||
|
||||
// clear out the last cards played
|
||||
_trickCardGame.setLastCardsPlayed(null);
|
||||
|
||||
// initialize the turn duration scales
|
||||
float[] scales = new float[_cardGame.getPlayerCount()];
|
||||
Arrays.fill(scales, 1.0f);
|
||||
_trickCardGame.setTurnDurationScales(scales);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game has started. Default implementation starts the
|
||||
* first hand.
|
||||
*/
|
||||
public void gameDidStart ()
|
||||
{
|
||||
super.gameDidStart();
|
||||
|
||||
// start the first hand
|
||||
startHand();
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void gameDidEnd ()
|
||||
{
|
||||
super.gameDidEnd();
|
||||
|
||||
// make sure all intervals are cancelled
|
||||
_turnTimeoutInterval.cancel();
|
||||
_endTrickInterval.cancel();
|
||||
|
||||
// make sure trick state is back to between hands
|
||||
if (_trickCardGame.getTrickState() !=
|
||||
TrickCardGameObject.BETWEEN_HANDS) {
|
||||
_trickCardGame.setTrickState(TrickCardGameObject.BETWEEN_HANDS);
|
||||
}
|
||||
|
||||
// initialize the array of rematch requests
|
||||
_trickCardGame.setRematchRequests(
|
||||
new int[_cardGame.getPlayerCount()]);
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void startTurn ()
|
||||
{
|
||||
super.startTurn();
|
||||
|
||||
// initialize the timeout flag and schedule the timeout interval
|
||||
_turnTimedOut = false;
|
||||
_turnTimeoutInterval.schedule(_trickCardGame.getTurnDuration());
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void endTurn ()
|
||||
{
|
||||
// cancel the timeout interval
|
||||
_turnTimeoutInterval.cancel();
|
||||
|
||||
// reduce or increase the turn duration scale
|
||||
if (_turnTimedOut) {
|
||||
reduceTurnDurationScale(_turnIdx);
|
||||
|
||||
} else {
|
||||
increaseTurnDurationScale(_turnIdx);
|
||||
}
|
||||
|
||||
super.endTurn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a hand of cards. Calls {@link #handWillStart}, sets the trick
|
||||
* state to PLAYING_HAND, and calls {@link #handDidStart}.
|
||||
*/
|
||||
public void startHand ()
|
||||
{
|
||||
handWillStart();
|
||||
_trickCardGame.setTrickState(TrickCardGameObject.PLAYING_HAND);
|
||||
handDidStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the hand of cards. Calls {@link #handWillEnd}, sets the trick
|
||||
* state to BETWEEN_HANDS, and calls {@link #handDidEnd}.
|
||||
*/
|
||||
public void endHand ()
|
||||
{
|
||||
handWillEnd();
|
||||
_trickCardGame.setTrickState(TrickCardGameObject.BETWEEN_HANDS);
|
||||
handDidEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a trick. Calls {@link #trickWillStart}, sets the trick
|
||||
* state to PLAYING_TRICK, and calls {@link #trickDidStart}.
|
||||
*/
|
||||
public void startTrick ()
|
||||
{
|
||||
trickWillStart();
|
||||
_trickCardGame.setTrickState(TrickCardGameObject.PLAYING_TRICK);
|
||||
trickDidStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the trick. Calls {@link #trickWillEnd}, sets the trick
|
||||
* state to PLAYING_HAND, and calls {@link #trickDidEnd}.
|
||||
*/
|
||||
public void endTrick ()
|
||||
{
|
||||
trickWillEnd();
|
||||
_trickCardGame.setTrickState(TrickCardGameObject.PLAYING_HAND);
|
||||
trickDidEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request to transfer a group of cards between players.
|
||||
* Default implementation verifies that the user's hand contains the
|
||||
* specified cards, then calls {@link #sendCardsToPlayer(int, int,
|
||||
* Card[])}.
|
||||
*/
|
||||
public void sendCardsToPlayer (ClientObject client, int toidx,
|
||||
Card[] cards)
|
||||
{
|
||||
// make sure they're actually a player
|
||||
int fromidx = _cgmgr.getPlayerIndex(client);
|
||||
if (fromidx == -1) {
|
||||
Log.warning("Send request from non-player [username=" +
|
||||
((BodyObject)client).who() + ", cards=" +
|
||||
StringUtil.toString(cards) + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure they have the cards
|
||||
if (!_hands[fromidx].containsAll(cards)) {
|
||||
Log.warning("Tried to send cards not held [username=" +
|
||||
((BodyObject)client).who() + ", cards=" +
|
||||
StringUtil.toString(cards) + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// send the cards
|
||||
sendCardsToPlayer(fromidx, toidx, cards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends cards between players without error checking. Default
|
||||
* implementation transfers the cards between hands and notifies
|
||||
* everyone of the transfer using {@link
|
||||
* CardGameManager#transferCardsBetweenPlayers(int, int, Card[])}.
|
||||
*/
|
||||
protected void sendCardsToPlayer (int fromidx, int toidx, Card[] cards)
|
||||
{
|
||||
// remove from sending player's hand
|
||||
_hands[fromidx].removeAll(cards);
|
||||
|
||||
// add to receiving player's hand
|
||||
_hands[toidx].addAll(cards);
|
||||
|
||||
// notify everyone of the transfer
|
||||
_cgmgr.transferCardsBetweenPlayers(fromidx, toidx, cards);
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void playCard (ClientObject client, Card card, int handSize)
|
||||
{
|
||||
// make sure we're playing a trick
|
||||
if (_trickCardGame.getTrickState() !=
|
||||
TrickCardGameObject.PLAYING_TRICK) {
|
||||
return; // silently ignore play attempts after timeouts
|
||||
}
|
||||
|
||||
// make sure it's their turn
|
||||
Name username = ((BodyObject)client).getVisibleName();
|
||||
if (!username.equals(_trickCardGame.getTurnHolder())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure they're on the right trick
|
||||
int pidx = _cardGame.getPlayerIndex(username);
|
||||
if (_hands[pidx].size() != handSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure their hand contains the specified card
|
||||
if (!_hands[pidx].contains(card)) {
|
||||
Log.warning("Tried to play card not held [username=" + username +
|
||||
", card=" + card + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure the card is legal to play
|
||||
if (!_trickCardGame.isCardPlayable(_hands[pidx], card)) {
|
||||
Log.warning("Tried to play illegal card [username=" + username +
|
||||
", card=" + card + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// play the card
|
||||
playCard(pidx, card);
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays a card for a player without error checking.
|
||||
*/
|
||||
protected void playCard (int pidx, Card card)
|
||||
{
|
||||
((DObject) _trickCardGame).startTransaction();
|
||||
try {
|
||||
// play the card by removing it from the hand and adding it
|
||||
// to the end of the cards played array
|
||||
_hands[pidx].remove(card);
|
||||
PlayerCard[] cards = (PlayerCard[])ArrayUtil.append(
|
||||
_trickCardGame.getCardsPlayed(), new PlayerCard(pidx, card));
|
||||
_trickCardGame.setCardsPlayed(cards);
|
||||
|
||||
// end the user's turn
|
||||
endTurn();
|
||||
|
||||
// end the trick if everyone has played a card
|
||||
if (_turnIdx == -1) {
|
||||
if (_endTrickDelay == 0) {
|
||||
endTrick();
|
||||
|
||||
} else {
|
||||
_endTrickInterval.schedule(_endTrickDelay);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
((DObject) _trickCardGame).commitTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
public void requestRematch (ClientObject client)
|
||||
{
|
||||
// make sure the game is over
|
||||
if (_cardGame.state != CardGameObject.GAME_OVER) {
|
||||
Log.warning("Tried to request rematch when game wasn't over " +
|
||||
"[username=" + ((BodyObject)client).who() + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure the requester is one of the players
|
||||
int pidx = _cgmgr.getPlayerIndex(client);
|
||||
if (pidx == -1) {
|
||||
Log.warning("Rematch request from non-player [username=" +
|
||||
((BodyObject)client).who() + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure the player hasn't already requested
|
||||
if (_trickCardGame.getRematchRequests()[pidx] !=
|
||||
TrickCardGameObject.NO_REQUEST) {
|
||||
Log.warning("Repeated rematch request [username=" +
|
||||
((BodyObject)client).who() + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// if player is first requesting, set to request; else set
|
||||
// to accept
|
||||
int req = (getRematchRequestCount() == 0 ?
|
||||
TrickCardGameObject.REQUESTS_REMATCH :
|
||||
TrickCardGameObject.ACCEPTS_REMATCH);
|
||||
_trickCardGame.setRematchRequestsAt(req, pidx);
|
||||
|
||||
// if all players accept the rematch, restart the game
|
||||
if (getRematchRequestCount() == _cardGame.getPlayerCount()) {
|
||||
_cgmgr.rematchGame();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of players currently requesting or accepting
|
||||
* a rematch.
|
||||
*/
|
||||
protected int getRematchRequestCount ()
|
||||
{
|
||||
int[] rematchRequests = _trickCardGame.getRematchRequests();
|
||||
int count = 0;
|
||||
for (int i = 0; i < rematchRequests.length; i++) {
|
||||
if (rematchRequests[i] != TrickCardGameObject.NO_REQUEST) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the trick is complete--that is, whether each player has
|
||||
* played a card.
|
||||
*/
|
||||
protected boolean isTrickComplete ()
|
||||
{
|
||||
return _trickCardGame.getCardsPlayed().length ==
|
||||
_cardGame.getPlayerCount();
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
protected void setFirstTurnHolder ()
|
||||
{
|
||||
if (_trickCardGame.getTrickState() ==
|
||||
TrickCardGameObject.PLAYING_TRICK) {
|
||||
super.setFirstTurnHolder();
|
||||
|
||||
} else {
|
||||
_turnIdx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Documentation inherited.
|
||||
protected void setNextTurnHolder ()
|
||||
{
|
||||
if (_trickCardGame.getTrickState() ==
|
||||
TrickCardGameObject.PLAYING_TRICK &&
|
||||
!isTrickComplete()) {
|
||||
super.setNextTurnHolder();
|
||||
|
||||
} else {
|
||||
_turnIdx = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the current turn times out. Default implementation
|
||||
* plays a random playable card if in the trick-playing state.
|
||||
*/
|
||||
protected void turnTimedOut ()
|
||||
{
|
||||
if (_trickCardGame.getTrickState() ==
|
||||
TrickCardGameObject.PLAYING_TRICK) {
|
||||
playCard(_turnIdx, pickRandomPlayableCard(_hands[_turnIdx]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduces the specified player's turn duration due to a time-out.
|
||||
*/
|
||||
protected void reduceTurnDurationScale (int pidx)
|
||||
{
|
||||
float oldScale = _trickCardGame.getTurnDurationScales()[pidx],
|
||||
newScale = Math.max(oldScale - TURN_DURATION_SCALE_REDUCTION,
|
||||
MINIMUM_TURN_DURATION_SCALE);
|
||||
if (newScale != oldScale) {
|
||||
_trickCardGame.setTurnDurationScalesAt(newScale, pidx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increases the specified player's turn duration due to avoiding a
|
||||
* time-out.
|
||||
*/
|
||||
protected void increaseTurnDurationScale (int pidx)
|
||||
{
|
||||
float oldScale = _trickCardGame.getTurnDurationScales()[pidx],
|
||||
newScale = Math.min(oldScale + TURN_DURATION_SCALE_INCREASE,
|
||||
1.0f);
|
||||
if (newScale != oldScale) {
|
||||
_trickCardGame.setTurnDurationScalesAt(newScale, pidx);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random playable card from the specified hand.
|
||||
*/
|
||||
protected Card pickRandomPlayableCard (Hand hand)
|
||||
{
|
||||
ArrayList playableCards = new ArrayList();
|
||||
for (int i = 0; i < hand.size(); i++) {
|
||||
Card card = (Card)hand.get(i);
|
||||
if (_trickCardGame.isCardPlayable(hand, card)) {
|
||||
playableCards.add(card);
|
||||
}
|
||||
}
|
||||
return (Card)RandomUtil.pickRandom(playableCards);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the object that a new hand is about to start.
|
||||
*/
|
||||
protected void handWillStart ()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Notifies the object that a new hand has just started. Default
|
||||
* implementation prepares the deck, deals the hands, and starts the
|
||||
* first trick.
|
||||
*/
|
||||
protected void handDidStart ()
|
||||
{
|
||||
// prepare the deck
|
||||
prepareDeck();
|
||||
|
||||
// deal cards to players
|
||||
dealHands();
|
||||
|
||||
// start the first trick
|
||||
startTrick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the deck for a new hand of cards. Default implementation
|
||||
* resets to a full deck without jokers and shuffles.
|
||||
*/
|
||||
protected void prepareDeck ()
|
||||
{
|
||||
_deck.reset(false);
|
||||
_deck.shuffle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deals hands to the players. Default implementation deals the entire
|
||||
* deck to the players in equal-sized hands.
|
||||
*/
|
||||
protected void dealHands ()
|
||||
{
|
||||
_hands = _cgmgr.dealHands(_deck, _deck.size() /
|
||||
_cardGame.getPlayerCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the object that the hand is about to end.
|
||||
*/
|
||||
protected void handWillEnd ()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Notifies the object that the hand has ended. Default implementation
|
||||
* starts the next hand.
|
||||
*/
|
||||
protected void handDidEnd ()
|
||||
{
|
||||
startHand();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the object that a new trick is about to start. Default
|
||||
* implementation resets the array of cards played.
|
||||
*/
|
||||
protected void trickWillStart ()
|
||||
{
|
||||
_trickCardGame.setCardsPlayed(new PlayerCard[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the object that a new trick has started. Default
|
||||
* implementation sets the first turn holder and starts the
|
||||
* turn.
|
||||
*/
|
||||
protected void trickDidStart ()
|
||||
{
|
||||
setFirstTurnHolder();
|
||||
startTurn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the object that the trick is about to end.
|
||||
*/
|
||||
protected void trickWillEnd ()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Notifies the object that the trick has ended. Default implementation
|
||||
* records the last cards played and starts the next trick, unless a
|
||||
* player has run out of cards, in which case it ends the hand.
|
||||
*/
|
||||
protected void trickDidEnd ()
|
||||
{
|
||||
// store the trick results for late-joiners
|
||||
_trickCardGame.setLastCardsPlayed(_trickCardGame.getCardsPlayed());
|
||||
|
||||
// clear out the cards played in the trick
|
||||
_trickCardGame.setCardsPlayed(null);
|
||||
|
||||
// verify that each player has at least one card
|
||||
if (anyHandsEmpty()) {
|
||||
endHand();
|
||||
return;
|
||||
}
|
||||
|
||||
// everyone has cards; let's play another trick
|
||||
startTrick();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether any hands are empty.
|
||||
*/
|
||||
protected boolean anyHandsEmpty ()
|
||||
{
|
||||
for (int i = 0; i < _hands.length; i++) {
|
||||
if (_hands[i].isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** The card game manager. */
|
||||
protected CardGameManager _cgmgr;
|
||||
|
||||
/** The game object as trick card game. */
|
||||
protected TrickCardGameObject _trickCardGame;
|
||||
|
||||
/** The game object as card game. */
|
||||
protected CardGameObject _cardGame;
|
||||
|
||||
/** The amount of time to wait before ending the trick. */
|
||||
protected long _endTrickDelay;
|
||||
|
||||
/** The deck from which cards are dealt. */
|
||||
protected Deck _deck;
|
||||
|
||||
/** The hands of each player. */
|
||||
protected Hand[] _hands;
|
||||
|
||||
/** Whether or not the turn timed out. */
|
||||
protected boolean _turnTimedOut;
|
||||
|
||||
/** The all-purpose turn timeout interval. */
|
||||
protected Interval _turnTimeoutInterval =
|
||||
new Interval(PresentsServer.omgr) {
|
||||
public void expired () {
|
||||
_turnTimedOut = true;
|
||||
turnTimedOut();
|
||||
}
|
||||
};
|
||||
|
||||
/** Calls {@link #endTrick} upon expiration. */
|
||||
protected Interval _endTrickInterval = new Interval(PresentsServer.omgr) {
|
||||
public void expired () {
|
||||
endTrick();
|
||||
}
|
||||
};
|
||||
|
||||
/** Reduce turn duration scales by this amount each time the player times
|
||||
* out. */
|
||||
protected static final float TURN_DURATION_SCALE_REDUCTION = 0.25f;
|
||||
|
||||
/**
|
||||
* Increase turn duration scales by this amount each time the player
|
||||
* manages not to time out. */
|
||||
protected static final float TURN_DURATION_SCALE_INCREASE = 0.5f;
|
||||
|
||||
/** Don't let turn duration scales get below this level. */
|
||||
protected static final float MINIMUM_TURN_DURATION_SCALE = 0.1f;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.trick.client.TrickCardGameService;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationProvider;
|
||||
|
||||
/**
|
||||
* Defines the server-side of the {@link TrickCardGameService}.
|
||||
*/
|
||||
public interface TrickCardGameProvider extends InvocationProvider
|
||||
{
|
||||
/**
|
||||
* Handles a {@link TrickCardGameService#playCard} request.
|
||||
*/
|
||||
public void playCard (ClientObject caller, Card arg1, int arg2);
|
||||
|
||||
/**
|
||||
* Handles a {@link TrickCardGameService#requestRematch} request.
|
||||
*/
|
||||
public void requestRematch (ClientObject caller);
|
||||
|
||||
/**
|
||||
* Handles a {@link TrickCardGameService#sendCardsToPlayer} request.
|
||||
*/
|
||||
public void sendCardsToPlayer (ClientObject caller, int arg1, Card[] arg2);
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
//
|
||||
// $Id: TrickCardGameObject.java 3382 2005-03-03 19:55:35Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.util;
|
||||
|
||||
import com.threerings.parlor.card.data.Card;
|
||||
import com.threerings.parlor.card.data.Hand;
|
||||
import com.threerings.parlor.card.data.PlayerCard;
|
||||
import com.threerings.parlor.card.trick.data.TrickCardCodes;
|
||||
|
||||
/**
|
||||
* Methods of general utility to trick-taking card games.
|
||||
*/
|
||||
public class TrickCardGameUtil
|
||||
implements TrickCardCodes
|
||||
{
|
||||
/**
|
||||
* For four-player games with fixed partnerships, this returns the index
|
||||
* of the player's team.
|
||||
*
|
||||
* @param pidx the player index
|
||||
*/
|
||||
public static int getTeamIndex (int pidx)
|
||||
{
|
||||
return pidx & 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games with fixed partnerships, this returns the index
|
||||
* of the other team.
|
||||
*
|
||||
* @param tidx the index of the team
|
||||
*/
|
||||
public static int getOtherTeamIndex (int tidx)
|
||||
{
|
||||
return tidx ^ 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games with fixed partnerships, this returns the index
|
||||
* of the player's partner.
|
||||
*/
|
||||
public static int getPartnerIndex (int pidx)
|
||||
{
|
||||
return pidx ^ 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games with fixed partnerships, this returns the index
|
||||
* of one of the members of a team.
|
||||
*
|
||||
* @param tidx the index of the team
|
||||
* @param midx the index of the player within the team
|
||||
*/
|
||||
public static int getTeamMemberIndex (int tidx, int midx)
|
||||
{
|
||||
return (midx << 1) | tidx;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games, this returns the index of the player after the
|
||||
* specified player going clockwise around the table.
|
||||
*/
|
||||
public static int getNextInClockwiseSequence (int pidx)
|
||||
{
|
||||
// 2
|
||||
// 1 3
|
||||
// 0
|
||||
return (pidx + 1) & 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games with fixed partnerships, this returns the
|
||||
* relative location of one player from the point of view of another.
|
||||
*
|
||||
* @param pidx1 the index of the player to whom the location is relative
|
||||
* @param pidx2 the index of the player whose location is desired
|
||||
* @return the relative location (TOP, BOTTOM, LEFT, or RIGHT)
|
||||
*/
|
||||
public static int getRelativeLocation (int pidx1, int pidx2)
|
||||
{
|
||||
return (pidx2 - pidx1) & 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games, returns the index of the player to the left of
|
||||
* the specified player.
|
||||
*/
|
||||
public static int getLeftIndex (int pidx)
|
||||
{
|
||||
return (pidx + 1) & 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games, returns the index of the player to the right of
|
||||
* the specified player.
|
||||
*/
|
||||
public static int getRightIndex (int pidx)
|
||||
{
|
||||
return (pidx + 3) & 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* For four-player games, returns the index of the player across from the
|
||||
* specified player.
|
||||
*/
|
||||
public static int getOppositeIndex (int pidx)
|
||||
{
|
||||
return pidx ^ 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the player can follow the suit lead with the hand given.
|
||||
*/
|
||||
public static boolean canFollowSuit (PlayerCard[] cardsPlayed, Hand hand)
|
||||
{
|
||||
return hand.getSuitMemberCount(cardsPlayed[0].card.getSuit()) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the specified array contains the given card.
|
||||
*/
|
||||
public static boolean containsCard (PlayerCard[] cards, Card card)
|
||||
{
|
||||
for (int i = 0; i < cards.length; i++) {
|
||||
if (cards[i].card.equals(card)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of cards that belong to the specified suit within
|
||||
* the array given.
|
||||
*/
|
||||
public static int countSuitMembers (PlayerCard[] cards, int suit)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i = 0; i < cards.length; i++) {
|
||||
if (cards[i].card.getSuit() == suit) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the proposed card follows the suit lead.
|
||||
*/
|
||||
public static boolean followsSuit (PlayerCard[] cardsPlayed, Card card)
|
||||
{
|
||||
return cardsPlayed[0].card.getSuit() == card.getSuit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the highest card (according to the standard A,K,...,2 ordering)
|
||||
* in the suit lead, with an optional trump suit.
|
||||
*
|
||||
* @param trumpSuit the trump suit, or -1 for none
|
||||
*/
|
||||
public static PlayerCard getHighestInLeadSuit (PlayerCard[] cardsPlayed,
|
||||
int trumpSuit)
|
||||
{
|
||||
PlayerCard highest = cardsPlayed[0];
|
||||
for (int i = 1; i < cardsPlayed.length; i++) {
|
||||
PlayerCard other = cardsPlayed[i];
|
||||
if ((other.card.getSuit() == highest.card.getSuit() &&
|
||||
other.card.compareTo(highest.card) > 0) ||
|
||||
(other.card.getSuit() == trumpSuit &&
|
||||
highest.card.getSuit() != trumpSuit)) {
|
||||
highest = other;
|
||||
}
|
||||
}
|
||||
return highest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.samskivert.swing.SimpleSlider;
|
||||
import com.samskivert.swing.VGroupLayout;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.util.ParlorContext;
|
||||
|
||||
import com.threerings.parlor.game.client.SwingGameConfigurator;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides a default implementation of a TableConfigurator for
|
||||
* a Swing interface.
|
||||
*/
|
||||
public class DefaultSwingTableConfigurator extends TableConfigurator
|
||||
{
|
||||
/**
|
||||
* Create a TableConfigurator that allows only the specified number
|
||||
* of players and lets the configuring user enable private games
|
||||
* only if the number of players is greater than 2.
|
||||
*/
|
||||
public DefaultSwingTableConfigurator (int players)
|
||||
{
|
||||
this(players, (players > 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TableConfigurator that allows only the specified number
|
||||
* of players and lets the user configure a private table, or not.
|
||||
*/
|
||||
public DefaultSwingTableConfigurator (int players, boolean allowPrivate)
|
||||
{
|
||||
this(players, players, players, allowPrivate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TableConfigurator that allows for the specified configuration
|
||||
* parameters.
|
||||
*/
|
||||
public DefaultSwingTableConfigurator (int minPlayers,
|
||||
int desiredPlayers, int maxPlayers, boolean allowPrivate)
|
||||
{
|
||||
_config.minimumPlayerCount = minPlayers;
|
||||
|
||||
// create a slider for players, if applicable
|
||||
if (minPlayers != maxPlayers) {
|
||||
_playerSlider = new SimpleSlider(
|
||||
"", minPlayers, maxPlayers, desiredPlayers);
|
||||
|
||||
} else {
|
||||
_config.desiredPlayerCount = desiredPlayers;
|
||||
}
|
||||
|
||||
// create up the checkbox for private games, if applicable
|
||||
if (allowPrivate) {
|
||||
_privateCheck = new JCheckBox();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void createConfigInterface ()
|
||||
{
|
||||
super.createConfigInterface();
|
||||
|
||||
SwingGameConfigurator gconf = (SwingGameConfigurator) _gameConfigurator;
|
||||
|
||||
if (_playerSlider != null) {
|
||||
// TODO: proper translation
|
||||
gconf.addControl(new JLabel("Players:"), _playerSlider);
|
||||
}
|
||||
|
||||
if (_privateCheck != null) {
|
||||
// TODO: proper translation
|
||||
gconf.addControl(new JLabel("Private:"), _privateCheck);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean isEmpty ()
|
||||
{
|
||||
return (_playerSlider == null) && (_privateCheck == null);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void flushTableConfig()
|
||||
{
|
||||
super.flushTableConfig();
|
||||
|
||||
if (_playerSlider != null) {
|
||||
_config.desiredPlayerCount = _playerSlider.getValue();
|
||||
}
|
||||
if (_privateCheck != null) {
|
||||
_config.privateTable = _privateCheck.isSelected();
|
||||
}
|
||||
}
|
||||
|
||||
/** A slider for configuring the number of players at the table. */
|
||||
protected SimpleSlider _playerSlider;
|
||||
|
||||
/** A checkbox to allow the table creator to specify if the table is
|
||||
* private. */
|
||||
protected JCheckBox _privateCheck;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
//
|
||||
// $Id: GameReadyObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public boolean receivedGameReady (int gameOid);
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
//
|
||||
// $Id: Invitation.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.Log;
|
||||
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 ParlorCodes, 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 int inviteId = -1;
|
||||
|
||||
/** The name of the other user involved in this invitation. */
|
||||
public Name opponent;
|
||||
|
||||
/** The configuration of the game to be created. */
|
||||
public GameConfig config;
|
||||
|
||||
/** Constructs a new invitation record. */
|
||||
public Invitation (ParlorContext ctx, ParlorService pservice,
|
||||
Name opponent, GameConfig config,
|
||||
InvitationResponseObserver observer)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_pservice = pservice;
|
||||
_observer = observer;
|
||||
this.opponent = opponent;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts this invitation.
|
||||
*/
|
||||
public void accept ()
|
||||
{
|
||||
// generate the invocation service request
|
||||
_pservice.respond(_ctx.getClient(), inviteId,
|
||||
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 void refuse (String message)
|
||||
{
|
||||
// generate the invocation service request
|
||||
_pservice.respond(_ctx.getClient(), inviteId,
|
||||
INVITATION_REFUSED, message, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels this invitation.
|
||||
*/
|
||||
public void cancel ()
|
||||
{
|
||||
// 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(_ctx.getClient(), 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 void counter (GameConfig config, InvitationResponseObserver observer)
|
||||
{
|
||||
// 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(_ctx.getClient(), inviteId,
|
||||
INVITATION_COUNTERED, config, this);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void inviteReceived (int inviteId)
|
||||
{
|
||||
// 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(_ctx.getClient(), inviteId, this);
|
||||
} else {
|
||||
// otherwise, put it in the pending invites table
|
||||
_ctx.getParlorDirector().registerInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void requestFailed (String reason)
|
||||
{
|
||||
// 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.
|
||||
*/
|
||||
protected void receivedResponse (int code, Object arg)
|
||||
{
|
||||
// make sure we have an observer to notify
|
||||
if (_observer == null) {
|
||||
Log.warning("No observer registered for invitation " +
|
||||
this + ".");
|
||||
return;
|
||||
}
|
||||
|
||||
// notify the observer
|
||||
try {
|
||||
switch (code) {
|
||||
case INVITATION_ACCEPTED:
|
||||
_observer.invitationAccepted(this);
|
||||
break;
|
||||
|
||||
case INVITATION_REFUSED:
|
||||
_observer.invitationRefused(this, (String)arg);
|
||||
break;
|
||||
|
||||
case INVITATION_COUNTERED:
|
||||
_observer.invitationCountered(this, (GameConfig)arg);
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Invitation response observer choked on response " +
|
||||
"[code=" + code + ", arg=" + arg +
|
||||
", invite=" + this + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
|
||||
// unless the invitation was countered, we can remove it from the
|
||||
// pending table because it's resolved
|
||||
if (code != INVITATION_COUNTERED) {
|
||||
_ctx.getParlorDirector().clearInvitation(this);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns a string representation of this invitation record. */
|
||||
public String toString ()
|
||||
{
|
||||
return "[inviteId=" + inviteId + ", opponent=" + opponent +
|
||||
", config=" + config + ", observer=" + _observer +
|
||||
", cancelled=" + _cancelled + "]";
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Provides access to parlor services. */
|
||||
protected ParlorService _pservice;
|
||||
|
||||
/** The entity to notify when we receive a response for this
|
||||
* invitation. */
|
||||
protected InvitationResponseObserver _observer;
|
||||
|
||||
/** 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 boolean _cancelled = false;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
//
|
||||
// $Id: InvitationHandler.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public void invitationReceived (Invitation invite);
|
||||
|
||||
/**
|
||||
* Called when an invitation is cancelled by the inviting player.
|
||||
*
|
||||
* @param invite the cancelled invitation.
|
||||
*/
|
||||
public void invitationCancelled (Invitation invite);
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// $Id: InvitationResponseObserver.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public void invitationAccepted (Invitation invite);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void invitationRefused (Invitation invite, String message);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void invitationCountered (Invitation invite, GameConfig config);
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// $Id: ParlorDecoder.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.client.ParlorReceiver;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.presents.client.InvocationDecoder;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Dispatches calls to a {@link ParlorReceiver} instance.
|
||||
*/
|
||||
public class ParlorDecoder extends InvocationDecoder
|
||||
{
|
||||
/** The generated hash code used to identify this receiver class. */
|
||||
public static final String RECEIVER_CODE = "5ef9ee0d359c42a9024498ee9aad119a";
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#gameIsReady}
|
||||
* notifications. */
|
||||
public static final int GAME_IS_READY = 1;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInvite}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_INVITE = 2;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteCancellation}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_INVITE_CANCELLATION = 3;
|
||||
|
||||
/** The method id used to dispatch {@link ParlorReceiver#receivedInviteResponse}
|
||||
* notifications. */
|
||||
public static final int RECEIVED_INVITE_RESPONSE = 4;
|
||||
|
||||
/**
|
||||
* Creates a decoder that may be registered to dispatch invocation
|
||||
* service notifications to the specified receiver.
|
||||
*/
|
||||
public ParlorDecoder (ParlorReceiver receiver)
|
||||
{
|
||||
this.receiver = receiver;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public String getReceiverCode ()
|
||||
{
|
||||
return RECEIVER_CODE;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchNotification (int methodId, Object[] args)
|
||||
{
|
||||
switch (methodId) {
|
||||
case GAME_IS_READY:
|
||||
((ParlorReceiver)receiver).gameIsReady(
|
||||
((Integer)args[0]).intValue()
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE:
|
||||
((ParlorReceiver)receiver).receivedInvite(
|
||||
((Integer)args[0]).intValue(), (Name)args[1], (GameConfig)args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE_CANCELLATION:
|
||||
((ParlorReceiver)receiver).receivedInviteCancellation(
|
||||
((Integer)args[0]).intValue()
|
||||
);
|
||||
return;
|
||||
|
||||
case RECEIVED_INVITE_RESPONSE:
|
||||
((ParlorReceiver)receiver).receivedInviteResponse(
|
||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (Object)args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchNotification(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
//
|
||||
// $Id: ParlorDirector.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.util.ArrayList;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
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 ParlorCodes, ParlorReceiver
|
||||
{
|
||||
/**
|
||||
* 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 ParlorDirector (ParlorContext ctx)
|
||||
{
|
||||
super(ctx);
|
||||
_ctx = ctx;
|
||||
|
||||
// register ourselves with the invocation director as a parlor
|
||||
// notification receiver
|
||||
_ctx.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 void setInvitationHandler (InvitationHandler handler)
|
||||
{
|
||||
_handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified observer to the list of entities that are
|
||||
* notified when we receive a game ready notification.
|
||||
*/
|
||||
public void addGameReadyObserver (GameReadyObserver observer)
|
||||
{
|
||||
_grobs.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified observer from the list of entities that are
|
||||
* notified when we receive a game ready notification.
|
||||
*/
|
||||
public void removeGameReadyObserver (GameReadyObserver observer)
|
||||
{
|
||||
_grobs.remove(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 Invitation invite (Name invitee, GameConfig config,
|
||||
InvitationResponseObserver observer)
|
||||
{
|
||||
// create the invitation record
|
||||
Invitation invite = new Invitation(
|
||||
_ctx, _pservice, invitee, config, observer);
|
||||
// submit the invitation request to the server
|
||||
_pservice.invite(_ctx.getClient(), 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 void startSolitaire (
|
||||
GameConfig config, InvocationService.ConfirmListener listener)
|
||||
{
|
||||
_pservice.startSolitaire(_ctx.getClient(), config, listener);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clientDidLogoff (Client client)
|
||||
{
|
||||
super.clientDidLogoff(client);
|
||||
_pservice = null;
|
||||
_pendingInvites.clear();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
// get a handle on our parlor services
|
||||
_pservice = (ParlorService)client.requireService(ParlorService.class);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void gameIsReady (int gameOid)
|
||||
{
|
||||
Log.info("Handling game ready [goid=" + gameOid + "].");
|
||||
|
||||
// see what our observers have to say about it
|
||||
boolean handled = false;
|
||||
for (int i = 0; i < _grobs.size(); i++) {
|
||||
GameReadyObserver grob = (GameReadyObserver)_grobs.get(i);
|
||||
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) {
|
||||
_ctx.getLocationDirector().moveTo(gameOid);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void receivedInvite (int remoteId, Name inviter, GameConfig config)
|
||||
{
|
||||
// create an invitation record for this invitation
|
||||
Invitation invite = new Invitation(
|
||||
_ctx, _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 (Exception e) {
|
||||
Log.warning("Invitation handler choked on invite " +
|
||||
"notification " + invite + ".");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void receivedInviteResponse (
|
||||
int remoteId, int code, Object arg)
|
||||
{
|
||||
// look up the invitation record for this invitation
|
||||
Invitation invite = (Invitation)_pendingInvites.get(remoteId);
|
||||
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 void receivedInviteCancellation (int remoteId)
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new invitation in our pending invitations table. The
|
||||
* invitation will call this when it knows its invitation id.
|
||||
*/
|
||||
protected void registerInvitation (Invitation invite)
|
||||
{
|
||||
_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.
|
||||
*/
|
||||
protected void clearInvitation (Invitation invite)
|
||||
{
|
||||
_pendingInvites.remove(invite.inviteId);
|
||||
}
|
||||
|
||||
/** An active parlor context. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Provides access to parlor server side services. */
|
||||
protected ParlorService _pservice;
|
||||
|
||||
/** The entity that has registered itself to handle incoming
|
||||
* invitation notifications. */
|
||||
protected InvitationHandler _handler;
|
||||
|
||||
/** A table of acknowledged (but not yet accepted or refused)
|
||||
* invitation requests, keyed on invitation id. */
|
||||
protected HashIntMap _pendingInvites = new HashIntMap();
|
||||
|
||||
/** We notify the entities on this list when we get a game ready
|
||||
* notification. */
|
||||
protected ArrayList _grobs = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// $Id: ParlorReceiver.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.data.ParlorCodes;
|
||||
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.
|
||||
*/
|
||||
public void gameIsReady (int gameOid);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void receivedInvite (int remoteId, Name inviter, GameConfig config);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void receivedInviteResponse (int remoteId, int code, Object arg);
|
||||
|
||||
/**
|
||||
* Called by the invocation services when an outstanding invitation
|
||||
* has been cancelled by the inviting user.
|
||||
*
|
||||
* @param remoteId the indentifier of the cancelled invitation.
|
||||
*/
|
||||
public void receivedInviteCancellation (int remoteId);
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//
|
||||
// $Id: ParlorService.java 3525 2005-04-26 02:38:42Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
|
||||
/**
|
||||
* Provides an interface to the various parlor invocation services.
|
||||
* Presently these services are limited to the various matchmaking
|
||||
* mechanisms. It is unlikely that client code will want to make direct
|
||||
* use of this class, instead they would make use of the programmatic
|
||||
* interface provided by the {@link ParlorDirector}.
|
||||
*/
|
||||
public interface ParlorService extends InvocationService
|
||||
{
|
||||
/**
|
||||
* Used to communicate responses to {@link #invite} requests.
|
||||
*/
|
||||
public static interface InviteListener extends InvocationListener
|
||||
{
|
||||
/**
|
||||
* Called in response to a successful {@link #invite} request.
|
||||
*/
|
||||
public void inviteReceived (int inviteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to generate
|
||||
* your invitation request via {@link ParlorDirector#invite}. Requests
|
||||
* that an invitation be delivered to the named user, requesting that
|
||||
* they join the inviting user in a game, the details of which are
|
||||
* specified in the supplied game config object.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param invitee the username of the user to be invited.
|
||||
* @param config a game config object detailing the type and
|
||||
* configuration of the game to be created.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void invite (Client client, Name invitee, GameConfig config,
|
||||
InviteListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call one
|
||||
* of {@link Invitation#accept}, {@link Invitation#refuse}, or {@link
|
||||
* Invitation#counter}. Requests that an invitation response be
|
||||
* delivered with the specified parameters.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param inviteId the unique id previously assigned by the server to
|
||||
* this invitation.
|
||||
* @param code the response code to use in responding to the
|
||||
* invitation.
|
||||
* @param arg the argument associated with the response (a string
|
||||
* message from the player explaining why the response was refused in
|
||||
* the case of an invitation refusal or an updated game configuration
|
||||
* object in the case of a counter-invitation, or null in the case of
|
||||
* an accepted invitation).
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void respond (Client client, int inviteId, int code, Object arg,
|
||||
InvocationListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link Invitation#cancel}. Requests that an outstanding
|
||||
* invitation be cancelled.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param inviteId the unique id previously assigned by the server to
|
||||
* this invitation.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void cancel (Client client, int inviteId,
|
||||
InvocationListener listener);
|
||||
|
||||
/**
|
||||
* Used to communicate responses to {@link #createTable}, {@link
|
||||
* #joinTable}, and {@link #leaveTable} requests.
|
||||
*/
|
||||
public static interface TableListener extends InvocationListener
|
||||
{
|
||||
public void tableCreated (int tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link TableDirector#createTable}. Requests that a new table be
|
||||
* created.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param lobbyOid the oid of the lobby that will contain the newly
|
||||
* created table.
|
||||
* @param tableConfig the table configuration parameters.
|
||||
* @param config the game config for the game to be matchmade by the
|
||||
* table.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void createTable (Client client, int lobbyOid,
|
||||
TableConfig tableConfig, GameConfig config, TableListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link TableDirector#joinTable}. Requests that the current user
|
||||
* be added to the specified table at the specified position.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param lobbyOid the oid of the lobby that contains the table.
|
||||
* @param tableId the unique id of the table to which this user wishes
|
||||
* to be added.
|
||||
* @param position the position at the table to which this user desires
|
||||
* to be added.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void joinTable (Client client, int lobbyOid, int tableId,
|
||||
int position, InvocationListener listener);
|
||||
|
||||
/**
|
||||
* You probably don't want to call this directly, but want to call
|
||||
* {@link TableDirector#leaveTable}. Requests that the current user be
|
||||
* removed from the specified table.
|
||||
*
|
||||
* @param client a connected, operational client instance.
|
||||
* @param lobbyOid the oid of the lobby that contains the table.
|
||||
* @param tableId the unique id of the table from which this user
|
||||
* wishes to be removed.
|
||||
* @param listener will receive and process the response.
|
||||
*/
|
||||
public void leaveTable (Client client, int lobbyOid, int tableId,
|
||||
InvocationListener listener);
|
||||
|
||||
/**
|
||||
* Requests to start a single player game with the specified game
|
||||
* configuration.
|
||||
*/
|
||||
public void startSolitaire (Client client, GameConfig config,
|
||||
ConfirmListener listener);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// $Id: SeatednessObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public void seatednessDidChange (boolean isSeated);
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.util.ParlorContext;
|
||||
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
|
||||
import com.threerings.parlor.game.client.GameConfigurator;
|
||||
|
||||
/**
|
||||
* 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 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 void setTableConfig (TableConfig config)
|
||||
{
|
||||
if (config != null) {
|
||||
_config = config;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the TableConfigurator.
|
||||
*
|
||||
* At the time this is called, the GameConfigurator should have
|
||||
* already been initialized.
|
||||
*/
|
||||
public void init (ParlorContext ctx, GameConfigurator gameConfigurator)
|
||||
{
|
||||
_ctx = ctx;
|
||||
_gameConfigurator = gameConfigurator;
|
||||
createConfigInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the table config object that will be used.
|
||||
*/
|
||||
protected TableConfig createTableConfig ()
|
||||
{
|
||||
return new TableConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the config interface.
|
||||
*/
|
||||
protected void createConfigInterface ()
|
||||
{
|
||||
// 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 boolean isEmpty ();
|
||||
|
||||
/**
|
||||
* Return the fully configured table config according to the currently
|
||||
* configured user interface elements.
|
||||
*/
|
||||
public TableConfig getTableConfig ()
|
||||
{
|
||||
flushTableConfig();
|
||||
return _config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derived classes will want to override this method, flushing
|
||||
* values from the user interface to the table config object.
|
||||
*/
|
||||
protected void flushTableConfig ()
|
||||
{
|
||||
// nothing by default
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** The config we're configurating. */
|
||||
protected TableConfig _config;
|
||||
|
||||
/** The game configurator, which we may wish to reference. */
|
||||
protected GameConfigurator _gameConfigurator;
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
//
|
||||
// $Id: TableDirector.java 3758 2005-11-10 23:18:58Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.util.ArrayList;
|
||||
|
||||
import com.threerings.presents.client.BasicDirector;
|
||||
import com.threerings.presents.client.Client;
|
||||
|
||||
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.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
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> 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.
|
||||
*/
|
||||
public class TableDirector extends BasicDirector
|
||||
implements SetListener, ParlorService.TableListener
|
||||
{
|
||||
/**
|
||||
* 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 observer the entity that will receive callbacks when things
|
||||
* happen to the tables.
|
||||
*/
|
||||
public TableDirector (
|
||||
ParlorContext ctx, String tableField, TableObserver observer)
|
||||
{
|
||||
super(ctx);
|
||||
|
||||
// keep track of this stuff
|
||||
_ctx = ctx;
|
||||
_tableField = tableField;
|
||||
_observer = observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called by the entity that uses the table director when
|
||||
* the using entity prepares to enter and display a place. It is
|
||||
* assumed that the client is already subscribed to the provided place
|
||||
* object.
|
||||
*/
|
||||
public void willEnterPlace (PlaceObject place)
|
||||
{
|
||||
// add ourselves as a listener to the place object
|
||||
place.addListener(this);
|
||||
|
||||
// and remember this for later
|
||||
_lobby = place;
|
||||
}
|
||||
|
||||
/**
|
||||
* This must be called by the entity that uses the table director when
|
||||
* the using entity has left and is done displaying a place.
|
||||
*/
|
||||
public void didLeavePlace (PlaceObject place)
|
||||
{
|
||||
// remove our listenership
|
||||
place.removeListener(this);
|
||||
|
||||
// clear out our lobby reference
|
||||
_lobby = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void addSeatednessObserver (SeatednessObserver observer)
|
||||
{
|
||||
_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 void removeSeatednessObserver (SeatednessObserver observer)
|
||||
{
|
||||
_seatedObservers.remove(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this client is currently seated at a table, false
|
||||
* if they are not.
|
||||
*/
|
||||
public boolean isSeated ()
|
||||
{
|
||||
return (_ourTable != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void createTable (TableConfig tableConfig, GameConfig config)
|
||||
{
|
||||
// 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 (_lobby == 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
|
||||
_pservice.createTable(_ctx.getClient(), _lobby.getOid(), 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 void joinTable (int tableId, int position)
|
||||
{
|
||||
// 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 (_lobby == null) {
|
||||
Log.warning("Requested to join a table but we're not " +
|
||||
"currently in a place [tableId=" + tableId + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// issue the join request
|
||||
_pservice.joinTable(_ctx.getClient(), _lobby.getOid(), 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 void leaveTable (int tableId)
|
||||
{
|
||||
// make sure we're currently in a place
|
||||
if (_lobby == null) {
|
||||
Log.warning("Requested to leave a table but we're not " +
|
||||
"currently in a place [tableId=" + tableId + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// issue the leave request
|
||||
_pservice.leaveTable(_ctx.getClient(), _lobby.getOid(), tableId, this);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void clientDidLogoff (Client client)
|
||||
{
|
||||
super.clientDidLogoff(client);
|
||||
_pservice = null;
|
||||
_lobby = null;
|
||||
_ourTable = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void fetchServices (Client client)
|
||||
{
|
||||
// get a handle on our parlor services
|
||||
_pservice = (ParlorService)client.requireService(ParlorService.class);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void entryAdded (EntryAddedEvent event)
|
||||
{
|
||||
if (event.getName().equals(_tableField)) {
|
||||
Table table = (Table)event.getEntry();
|
||||
|
||||
// check to see if we just joined a table
|
||||
checkSeatedness(table);
|
||||
|
||||
// now let the observer know what's up
|
||||
_observer.tableAdded(table);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void entryUpdated (EntryUpdatedEvent event)
|
||||
{
|
||||
if (event.getName().equals(_tableField)) {
|
||||
Table table = (Table)event.getEntry();
|
||||
|
||||
// check to see if we just joined or left a table
|
||||
checkSeatedness(table);
|
||||
|
||||
// now let the observer know what's up
|
||||
_observer.tableUpdated(table);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void entryRemoved (EntryRemovedEvent event)
|
||||
{
|
||||
if (event.getName().equals(_tableField)) {
|
||||
Integer tableId = (Integer)event.getKey();
|
||||
|
||||
// check to see if our table just disappeared
|
||||
if (_ourTable != null && tableId.equals(_ourTable.tableId)) {
|
||||
_ourTable = null;
|
||||
notifySeatedness(false);
|
||||
}
|
||||
|
||||
// now let the observer know what's up
|
||||
_observer.tableRemoved(tableId.intValue());
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void tableCreated (int tableId)
|
||||
{
|
||||
// nothing much to do here
|
||||
Log.info("Table creation succeeded [tableId=" + tableId + "].");
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
public void requestFailed (String reason)
|
||||
{
|
||||
Log.warning("Table creation failed [reason=" + reason + "].");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if we're a member of this table and notes it as our
|
||||
* table, if so.
|
||||
*/
|
||||
protected void checkSeatedness (Table table)
|
||||
{
|
||||
Table oldTable = _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 occupants array
|
||||
BodyObject self = (BodyObject)_ctx.getClient().getClientObject();
|
||||
for (int i = 0; i < table.occupants.length; i++) {
|
||||
if (self.getVisibleName().equals(table.occupants[i])) {
|
||||
_ourTable = table;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if nothing changed, bail now
|
||||
if (oldTable == _ourTable ||
|
||||
(oldTable != null && oldTable.equals(_ourTable))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise notify the observers
|
||||
notifySeatedness(_ourTable != null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the seatedness observers of a seatedness change.
|
||||
*/
|
||||
protected void notifySeatedness (boolean isSeated)
|
||||
{
|
||||
int slength = _seatedObservers.size();
|
||||
for (int i = 0; i < slength; i++) {
|
||||
SeatednessObserver observer = (SeatednessObserver)
|
||||
_seatedObservers.get(i);
|
||||
try {
|
||||
observer.seatednessDidChange(isSeated);
|
||||
} catch (Exception e) {
|
||||
Log.warning("Observer choked in seatednessDidChange() " +
|
||||
"[observer=" + observer + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** A context by which we can access necessary client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Parlor server-side services. */
|
||||
protected ParlorService _pservice;
|
||||
|
||||
/** The place object in which we're currently managing tables. */
|
||||
protected PlaceObject _lobby;
|
||||
|
||||
/** The field name of the distributed set that contains our tables. */
|
||||
protected String _tableField;
|
||||
|
||||
/** The entity that we talk to when table stuff happens. */
|
||||
protected TableObserver _observer;
|
||||
|
||||
/** The table of which we are a member if any. */
|
||||
protected Table _ourTable;
|
||||
|
||||
/** An array of entities that want to hear about when we stand up or
|
||||
* sit down. */
|
||||
protected ArrayList _seatedObservers = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// $Id: TableObserver.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public void tableAdded (Table table);
|
||||
|
||||
/**
|
||||
* Called when something has changed about a table (occupant list
|
||||
* updated, state changed from matchmaking to in-play, etc.).
|
||||
*/
|
||||
public void tableUpdated (Table table);
|
||||
|
||||
/**
|
||||
* Called when a table goes away.
|
||||
*/
|
||||
public void tableRemoved (int tableId);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// $Id: ParlorCodes.java 3359 2005-02-19 22:38:06Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 interface ParlorCodes extends InvocationCodes
|
||||
{
|
||||
/** The response code for an accepted invitation. */
|
||||
public static final int INVITATION_ACCEPTED = 0;
|
||||
|
||||
/** The response code for a refused invitation. */
|
||||
public static final int INVITATION_REFUSED = 1;
|
||||
|
||||
/** The response code for a countered invitation. */
|
||||
public static final int INVITATION_COUNTERED = 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 final String INVITEE_NOT_ONLINE = "m.invitee_not_online";
|
||||
|
||||
/** An error code returned when a user requests to join a table that
|
||||
* doesn't exist. */
|
||||
public static final String NO_SUCH_TABLE = "m.no_such_table";
|
||||
|
||||
/** An error code returned when a user requests to join a table at a
|
||||
* position that is not valid. */
|
||||
public static final String INVALID_TABLE_POSITION =
|
||||
"m.invalid_table_position";
|
||||
|
||||
/** An error code returned when a user requests to join a table in a
|
||||
* position that is already occupied. */
|
||||
public static final String TABLE_POSITION_OCCUPIED =
|
||||
"m.table_position_occupied";
|
||||
|
||||
/** An error code returned when a user requests to leave a table that
|
||||
* they were not sitting at in the first place. */
|
||||
public static final String NOT_AT_TABLE = "m.not_at_table";
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// $Id: ParlorMarshaller.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.client.ParlorService;
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the {@link ParlorService} 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
|
||||
{
|
||||
// documentation inherited
|
||||
public static class InviteMarshaller extends ListenerMarshaller
|
||||
implements InviteListener
|
||||
{
|
||||
/** The method id used to dispatch {@link #inviteReceived}
|
||||
* responses. */
|
||||
public static final int INVITE_RECEIVED = 1;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void inviteReceived (int arg1)
|
||||
{
|
||||
_invId = null;
|
||||
omgr.postEvent(new InvocationResponseEvent(
|
||||
callerOid, requestId, INVITE_RECEIVED,
|
||||
new Object[] { Integer.valueOf(arg1) }));
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchResponse (int methodId, Object[] args)
|
||||
{
|
||||
switch (methodId) {
|
||||
case INVITE_RECEIVED:
|
||||
((InviteListener)listener).inviteReceived(
|
||||
((Integer)args[0]).intValue());
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public static class TableMarshaller extends ListenerMarshaller
|
||||
implements TableListener
|
||||
{
|
||||
/** The method id used to dispatch {@link #tableCreated}
|
||||
* responses. */
|
||||
public static final int TABLE_CREATED = 1;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void tableCreated (int arg1)
|
||||
{
|
||||
_invId = null;
|
||||
omgr.postEvent(new InvocationResponseEvent(
|
||||
callerOid, requestId, TABLE_CREATED,
|
||||
new Object[] { Integer.valueOf(arg1) }));
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchResponse (int methodId, Object[] args)
|
||||
{
|
||||
switch (methodId) {
|
||||
case TABLE_CREATED:
|
||||
((TableListener)listener).tableCreated(
|
||||
((Integer)args[0]).intValue());
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchResponse(methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #cancel} requests. */
|
||||
public static final int CANCEL = 1;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void cancel (Client arg1, int arg2, InvocationService.InvocationListener arg3)
|
||||
{
|
||||
ListenerMarshaller listener3 = new ListenerMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(arg1, CANCEL, new Object[] {
|
||||
Integer.valueOf(arg2), listener3
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #createTable} requests. */
|
||||
public static final int CREATE_TABLE = 2;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void createTable (Client arg1, int arg2, TableConfig arg3, GameConfig arg4, ParlorService.TableListener arg5)
|
||||
{
|
||||
ParlorMarshaller.TableMarshaller listener5 = new ParlorMarshaller.TableMarshaller();
|
||||
listener5.listener = arg5;
|
||||
sendRequest(arg1, CREATE_TABLE, new Object[] {
|
||||
Integer.valueOf(arg2), arg3, arg4, listener5
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #invite} requests. */
|
||||
public static final int INVITE = 3;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void invite (Client arg1, Name arg2, GameConfig arg3, ParlorService.InviteListener arg4)
|
||||
{
|
||||
ParlorMarshaller.InviteMarshaller listener4 = new ParlorMarshaller.InviteMarshaller();
|
||||
listener4.listener = arg4;
|
||||
sendRequest(arg1, INVITE, new Object[] {
|
||||
arg2, arg3, listener4
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #joinTable} requests. */
|
||||
public static final int JOIN_TABLE = 4;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void joinTable (Client arg1, int arg2, int arg3, int arg4, InvocationService.InvocationListener arg5)
|
||||
{
|
||||
ListenerMarshaller listener5 = new ListenerMarshaller();
|
||||
listener5.listener = arg5;
|
||||
sendRequest(arg1, JOIN_TABLE, new Object[] {
|
||||
Integer.valueOf(arg2), Integer.valueOf(arg3), Integer.valueOf(arg4), listener5
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #leaveTable} requests. */
|
||||
public static final int LEAVE_TABLE = 5;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void leaveTable (Client arg1, int arg2, int arg3, InvocationService.InvocationListener arg4)
|
||||
{
|
||||
ListenerMarshaller listener4 = new ListenerMarshaller();
|
||||
listener4.listener = arg4;
|
||||
sendRequest(arg1, LEAVE_TABLE, new Object[] {
|
||||
Integer.valueOf(arg2), Integer.valueOf(arg3), listener4
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #respond} requests. */
|
||||
public static final int RESPOND = 6;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void respond (Client arg1, int arg2, int arg3, Object arg4, InvocationService.InvocationListener arg5)
|
||||
{
|
||||
ListenerMarshaller listener5 = new ListenerMarshaller();
|
||||
listener5.listener = arg5;
|
||||
sendRequest(arg1, RESPOND, new Object[] {
|
||||
Integer.valueOf(arg2), Integer.valueOf(arg3), arg4, listener5
|
||||
});
|
||||
}
|
||||
|
||||
/** The method id used to dispatch {@link #startSolitaire} requests. */
|
||||
public static final int START_SOLITAIRE = 7;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void startSolitaire (Client arg1, GameConfig arg2, InvocationService.ConfirmListener arg3)
|
||||
{
|
||||
InvocationMarshaller.ConfirmMarshaller listener3 = new InvocationMarshaller.ConfirmMarshaller();
|
||||
listener3.listener = arg3;
|
||||
sendRequest(arg1, START_SOLITAIRE, new Object[] {
|
||||
arg2, listener3
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
//
|
||||
// $Id: Table.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.samskivert.util.ArrayIntSet;
|
||||
import com.samskivert.util.ListUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.DSet;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.game.data.PartyGameConfig;
|
||||
|
||||
/**
|
||||
* This class represents a table that is being used to matchmake a game by
|
||||
* the Parlor services.
|
||||
*/
|
||||
public class Table
|
||||
implements DSet.Entry, ParlorCodes
|
||||
{
|
||||
/** The unique identifier for this table. */
|
||||
public Integer tableId;
|
||||
|
||||
/** The object id of the lobby object with which this table is
|
||||
* associated. */
|
||||
public int lobbyOid;
|
||||
|
||||
/** The oid of the game that was created from this table or -1 if the
|
||||
* table is still in matchmaking mode. */
|
||||
public int gameOid = -1;
|
||||
|
||||
/** An array of the usernames of the occupants of this table (some
|
||||
* slots may not be filled), or null if a party game. */
|
||||
public Name[] occupants;
|
||||
|
||||
/** The body oids of the occupants of this table, or null if a party game.
|
||||
* (This is not propagated to remote instances.) */
|
||||
public transient int[] bodyOids;
|
||||
|
||||
/** The game config for the game that is being matchmade. */
|
||||
public GameConfig config;
|
||||
|
||||
/** The table configuration object. */
|
||||
public TableConfig tconfig;
|
||||
|
||||
/**
|
||||
* Creates a new table instance, and assigns it the next monotonically
|
||||
* increasing table id.
|
||||
*
|
||||
* @param lobbyOid the object id of the lobby in which this table is
|
||||
* to live.
|
||||
* @param tconfig the table configuration for this table.
|
||||
* @param config the configuration of the game being matchmade by this
|
||||
* table.
|
||||
*/
|
||||
public Table (int lobbyOid, TableConfig tconfig, GameConfig config)
|
||||
{
|
||||
// assign a unique table id
|
||||
tableId = Integer.valueOf(++_tableIdCounter);
|
||||
|
||||
// keep track of our lobby oid
|
||||
this.lobbyOid = lobbyOid;
|
||||
|
||||
// keep a casted reference around
|
||||
this.tconfig = tconfig;
|
||||
this.config = config;
|
||||
|
||||
// make room for the maximum number of players
|
||||
if (tconfig.desiredPlayerCount != -1) {
|
||||
occupants = new Name[tconfig.desiredPlayerCount];
|
||||
bodyOids = new int[occupants.length];
|
||||
|
||||
// fill in information on the AIs
|
||||
int acount = (config.ais == null) ? 0 : config.ais.length;
|
||||
for (int ii = 0; ii < acount; ii++) {
|
||||
// TODO: handle this naming business better
|
||||
occupants[ii] = new Name("AI " + (ii+1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a blank table instance, suitable for unserialization.
|
||||
*/
|
||||
public Table ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience function for accessing the table id as an int.
|
||||
*/
|
||||
public int getTableId ()
|
||||
{
|
||||
return tableId.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there is no one sitting at this table.
|
||||
*/
|
||||
public boolean isEmpty ()
|
||||
{
|
||||
for (int i = 0; i < bodyOids.length; i++) {
|
||||
if (bodyOids[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of players currently occupying this table.
|
||||
*/
|
||||
public int getOccupiedCount ()
|
||||
{
|
||||
int count = 0;
|
||||
for (int ii = 0; ii < occupants.length; ii++) {
|
||||
if (occupants[ii] != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Name[] getPlayers ()
|
||||
{
|
||||
if (isPartyGame()) {
|
||||
return occupants;
|
||||
}
|
||||
|
||||
// create and populate the players array
|
||||
Name[] players = new Name[getOccupiedCount()];
|
||||
for (int ii = 0, dex = 0; ii < occupants.length; ii++) {
|
||||
if (occupants[ii] != null) {
|
||||
players[dex++] = occupants[ii];
|
||||
}
|
||||
}
|
||||
|
||||
return players;
|
||||
}
|
||||
|
||||
/**
|
||||
* For a team game, get the team member indices of the compressed
|
||||
* players array returned by getPlayers().
|
||||
*/
|
||||
public int[][] getTeamMemberIndices ()
|
||||
{
|
||||
int[][] teams = tconfig.teamMemberIndices;
|
||||
if (teams == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// compress the team indexes down
|
||||
ArrayIntSet set = new ArrayIntSet();
|
||||
int[][] newTeams = new int[teams.length][];
|
||||
Name[] players = getPlayers();
|
||||
for (int ii=0; ii < teams.length; ii++) {
|
||||
set.clear();
|
||||
for (int jj=0; jj < teams[ii].length; jj++) {
|
||||
Name occ = occupants[teams[ii][jj]];
|
||||
if (occ != null) {
|
||||
set.add(ListUtil.indexOf(players, occ));
|
||||
}
|
||||
}
|
||||
newTeams[ii] = set.toIntArray();
|
||||
}
|
||||
|
||||
return newTeams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the game is a party game.
|
||||
*/
|
||||
public boolean isPartyGame ()
|
||||
{
|
||||
return (PartyGameConfig.NOT_PARTY_GAME != getPartyGameType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of party game being played at this table, or
|
||||
* PartyGameConfig.NOT_PARTY_GAME.
|
||||
*/
|
||||
public byte getPartyGameType ()
|
||||
{
|
||||
if (config instanceof PartyGameConfig) {
|
||||
return ((PartyGameConfig) config).getPartyGameType();
|
||||
|
||||
} else {
|
||||
return PartyGameConfig.NOT_PARTY_GAME;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to seat the specified user at the specified position in
|
||||
* this table.
|
||||
*
|
||||
* @param position the position in which to seat the user.
|
||||
* @param occupant the occupant to set.
|
||||
*
|
||||
* @return null if the user was successfully seated, a string error
|
||||
* code explaining the failure if the user was not able to be seated
|
||||
* at that position.
|
||||
*/
|
||||
public String setOccupant (int position, BodyObject occupant)
|
||||
{
|
||||
// make sure the requested position is a valid one
|
||||
if (position >= tconfig.desiredPlayerCount || position < 0) {
|
||||
return INVALID_TABLE_POSITION;
|
||||
}
|
||||
|
||||
// make sure the requested position is not already occupied
|
||||
if (occupants[position] != null) {
|
||||
return TABLE_POSITION_OCCUPIED;
|
||||
}
|
||||
|
||||
// otherwise all is well, stick 'em in
|
||||
setOccupantPos(position, occupant);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used for party games, it does no bounds checking
|
||||
* or verification of the player's ability to join, if you are unsure
|
||||
* you should call 'setOccupant'.
|
||||
*/
|
||||
public void setOccupantPos (int position, BodyObject occupant)
|
||||
{
|
||||
occupants[position] = occupant.getVisibleName();
|
||||
bodyOids[position] = occupant.getOid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified user be removed from their seat at this
|
||||
* table.
|
||||
*
|
||||
* @return true if the user was seated at the table and has now been
|
||||
* removed, false if the user was never seated at the table in the
|
||||
* first place.
|
||||
*/
|
||||
public boolean clearOccupant (Name username)
|
||||
{
|
||||
for (int i = 0; i < occupants.length; i++) {
|
||||
if (username.equals(occupants[i])) {
|
||||
clearOccupantPos(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the user identified by the specified body object id
|
||||
* be removed from their seat at this table.
|
||||
*
|
||||
* @return true if the user was seated at the table and has now been
|
||||
* removed, false if the user was never seated at the table in the
|
||||
* first place.
|
||||
*/
|
||||
public boolean clearOccupant (int bodyOid)
|
||||
{
|
||||
for (int i = 0; i < bodyOids.length; i++) {
|
||||
if (bodyOid == bodyOids[i]) {
|
||||
clearOccupantPos(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to clear an occupant at the specified position.
|
||||
* Only call this method if you know what you're doing.
|
||||
*/
|
||||
public void clearOccupantPos (int position)
|
||||
{
|
||||
occupants[position] = null;
|
||||
bodyOids[position] = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table has a sufficient number of occupants
|
||||
* that the game can be started.
|
||||
*/
|
||||
public boolean mayBeStarted ()
|
||||
{
|
||||
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
|
||||
int[][] teams = tconfig.teamMemberIndices;
|
||||
for (int ii=0; ii < teams.length; ii++) {
|
||||
int teamCount = 0;
|
||||
for (int jj=0; jj < teams[ii].length; jj++) {
|
||||
if (occupants[teams[ii][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 boolean shouldBeStarted ()
|
||||
{
|
||||
return tconfig.desiredPlayerCount <= getOccupiedCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this table is in play, false if it is still being
|
||||
* matchmade.
|
||||
*/
|
||||
public boolean inPlay ()
|
||||
{
|
||||
return gameOid != -1;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Comparable getKey ()
|
||||
{
|
||||
return tableId;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public boolean equals (Object other)
|
||||
{
|
||||
return (other instanceof Table) &&
|
||||
tableId.equals(((Table) other).tableId);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public int hashCode ()
|
||||
{
|
||||
return tableId.intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a string representation of this table instance.
|
||||
*/
|
||||
public String toString ()
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
buf.append(StringUtil.shortClassName(this));
|
||||
buf.append(" [");
|
||||
toString(buf);
|
||||
buf.append("]");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for toString, ripe for overrideability.
|
||||
*/
|
||||
protected void toString (StringBuilder buf)
|
||||
{
|
||||
buf.append("tableId=").append(tableId);
|
||||
buf.append(", lobbyOid=").append(lobbyOid);
|
||||
buf.append(", gameOid=").append(gameOid);
|
||||
buf.append(", occupants=").append(StringUtil.toString(occupants));
|
||||
buf.append(", config=").append(config);
|
||||
}
|
||||
|
||||
/** A counter for assigning table ids. */
|
||||
protected static int _tableIdCounter = 0;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// $Id: TableConfig.java 3604 2005-06-17 20:25:28Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.SimpleStreamableObject;
|
||||
|
||||
/**
|
||||
* 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,
|
||||
* or -1 for a party game. For team games, this should be set to the
|
||||
* total number of players overall, as teams may be unequal. */
|
||||
public int desiredPlayerCount;
|
||||
|
||||
/** 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 int minimumPlayerCount;
|
||||
|
||||
/** 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 int[][] teamMemberIndices;
|
||||
|
||||
/** Whether the table is "private". */
|
||||
public boolean privateTable;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
//
|
||||
// $Id: TableLobbyObject.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public DSet getTables ();
|
||||
|
||||
/**
|
||||
* Adds the supplied table instance to the tables set (using the
|
||||
* appropriate distributed object mechanisms).
|
||||
*/
|
||||
public void addToTables (Table table);
|
||||
|
||||
/**
|
||||
* Updates the value of the specified table instance in the tables
|
||||
* distributed set (using the appropriate distributed object
|
||||
* mechanisms).
|
||||
*/
|
||||
public void updateTables (Table table);
|
||||
|
||||
/**
|
||||
* Removes the table instance that matches the specified key from the
|
||||
* tables set (using the appropriate distributed object mechanisms).
|
||||
*/
|
||||
public void removeFromTables (Comparable key);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// $Id: GameConfigurator.java 3590 2005-06-08 23:20:18Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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}.
|
||||
*/
|
||||
public abstract class GameConfigurator
|
||||
{
|
||||
/**
|
||||
* Initializes this game configurator, creates its user interface
|
||||
* elements and prepares it for display.
|
||||
*/
|
||||
public void init (ParlorContext ctx)
|
||||
{
|
||||
// save this for later
|
||||
_ctx = ctx;
|
||||
|
||||
// create our interface elements
|
||||
createConfigInterface();
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation creates nothing.
|
||||
*/
|
||||
protected void createConfigInterface ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides this configurator with its configuration. It should set up
|
||||
* all of its user interface elements to reflect the configuration.
|
||||
*/
|
||||
public void setGameConfig (GameConfig config)
|
||||
{
|
||||
_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 void gotGameConfig ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a configured game configuration.
|
||||
*/
|
||||
public GameConfig getGameConfig ()
|
||||
{
|
||||
// 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 void flushGameConfig ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Provides access to client services. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Our game configuration. */
|
||||
protected GameConfig _config;
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
//
|
||||
// $Id: GameController.java 3804 2006-01-13 01:52:36Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.awt.event.ActionEvent;
|
||||
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
|
||||
import com.threerings.crowd.client.PlaceController;
|
||||
import com.threerings.crowd.client.PlaceControllerDelegate;
|
||||
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.Log;
|
||||
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.game.data.PartyGameConfig;
|
||||
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.
|
||||
*/
|
||||
public void init (CrowdContext ctx, PlaceConfig config)
|
||||
{
|
||||
// cast our references before we call super.init() so that when
|
||||
// super.init() calls createPlaceView(), we have our casted
|
||||
// references already in place
|
||||
_ctx = (ParlorContext)ctx;
|
||||
_config = (GameConfig)config;
|
||||
|
||||
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.
|
||||
*/
|
||||
public void willEnterPlace (PlaceObject plobj)
|
||||
{
|
||||
super.willEnterPlace(plobj);
|
||||
|
||||
// obtain a casted reference
|
||||
_gobj = (GameObject)plobj;
|
||||
|
||||
// if this place object is not our current location we'll need to
|
||||
// add it as an auxiliary chat source
|
||||
BodyObject bobj = (BodyObject)_ctx.getClient().getClientObject();
|
||||
if (bobj.location != plobj.getOid()) {
|
||||
_ctx.getChatDirector().addAuxiliarySource(
|
||||
_gobj, GameCodes.GAME_CHAT_TYPE);
|
||||
}
|
||||
|
||||
// and add ourselves as a listener
|
||||
_gobj.addListener(this);
|
||||
|
||||
// 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
|
||||
Log.info("Entering game " + _gobj.which() + ".");
|
||||
if (_gobj.getPlayerIndex(bobj.getVisibleName()) != -1) {
|
||||
_ctx.getClient().getRunQueue().postRunnable(new Runnable() {
|
||||
public void run () {
|
||||
// finally let the game manager know that we're ready
|
||||
// to roll
|
||||
playerReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes our listener registration from the game object and cleans
|
||||
* house.
|
||||
*/
|
||||
public void didLeavePlace (PlaceObject plobj)
|
||||
{
|
||||
super.didLeavePlace(plobj);
|
||||
|
||||
_ctx.getChatDirector().removeAuxiliarySource(_gobj);
|
||||
|
||||
// unlisten to the game object
|
||||
_gobj.removeListener(this);
|
||||
_gobj = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the game is over.
|
||||
*/
|
||||
public boolean isGameOver ()
|
||||
{
|
||||
boolean gameOver =
|
||||
((_gobj != null) ? (_gobj.state != GameObject.IN_PLAY) : true);
|
||||
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 void setGameOver (boolean gameOver)
|
||||
{
|
||||
_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 void resetGame ()
|
||||
{
|
||||
// let derived classes do their thing
|
||||
gameWillReset();
|
||||
|
||||
// end the game until we receive a new board
|
||||
setGameOver(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique round identifier for the current round.
|
||||
*/
|
||||
public int getRoundId ()
|
||||
{
|
||||
return (_gobj == null) ? -1 : _gobj.roundId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles basic game controller action events. Derived classes should
|
||||
* be sure to call <code>super.handleAction</code> for events they
|
||||
* don't specifically handle.
|
||||
*/
|
||||
public boolean handleAction (ActionEvent action)
|
||||
{
|
||||
return super.handleAction(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* A way for controllers to display a game-related system message.
|
||||
*/
|
||||
public void systemMessage (String bundle, String msg)
|
||||
{
|
||||
_ctx.getChatDirector().displayInfo(
|
||||
bundle, msg, GameCodes.GAME_CHAT_TYPE);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void attributeChanged (AttributeChangedEvent event)
|
||||
{
|
||||
// deal with game state changes
|
||||
if (event.getName().equals(GameObject.STATE)) {
|
||||
if (!stateDidChange(event.getIntValue())) {
|
||||
Log.warning("Game transitioned to unknown state " +
|
||||
"[gobj=" + _gobj +
|
||||
", state=" + event.getIntValue() + "].");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 boolean stateDidChange (int state)
|
||||
{
|
||||
switch (state) {
|
||||
case GameObject.IN_PLAY:
|
||||
gameDidStart();
|
||||
return true;
|
||||
case GameObject.GAME_OVER:
|
||||
gameDidEnd();
|
||||
return true;
|
||||
case GameObject.CANCELLED:
|
||||
gameWasCancelled();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void playerReady ()
|
||||
{
|
||||
Log.info("Reporting ready " + _gobj.which() + ".");
|
||||
_gobj.gameService.playerReady(_ctx.getClient());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void gameDidStart ()
|
||||
{
|
||||
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(new DelegateOp() {
|
||||
public void apply (PlaceControllerDelegate delegate) {
|
||||
((GameControllerDelegate)delegate).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 void gameDidEnd ()
|
||||
{
|
||||
// let our delegates do their business
|
||||
applyToDelegates(new DelegateOp() {
|
||||
public void apply (PlaceControllerDelegate delegate) {
|
||||
((GameControllerDelegate)delegate).gameDidEnd();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game was cancelled for some reason.
|
||||
*/
|
||||
protected void gameWasCancelled ()
|
||||
{
|
||||
// let our delegates do their business
|
||||
applyToDelegates(new DelegateOp() {
|
||||
public void apply (PlaceControllerDelegate delegate) {
|
||||
((GameControllerDelegate)delegate).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 void gameWillReset ()
|
||||
{
|
||||
// let our delegates do their business
|
||||
applyToDelegates(new DelegateOp() {
|
||||
public void apply (PlaceControllerDelegate delegate) {
|
||||
((GameControllerDelegate)delegate).gameWillReset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine if this game is a party game.
|
||||
*/
|
||||
protected boolean isPartyGame ()
|
||||
{
|
||||
return (_config instanceof PartyGameConfig) &&
|
||||
(((PartyGameConfig)_config).getPartyGameType() !=
|
||||
PartyGameConfig.NOT_PARTY_GAME);
|
||||
}
|
||||
|
||||
/** A reference to the active parlor context. */
|
||||
protected ParlorContext _ctx;
|
||||
|
||||
/** Our game configuration information. */
|
||||
protected GameConfig _config;
|
||||
|
||||
/** A reference to the game object for the game that we're
|
||||
* controlling. */
|
||||
protected GameObject _gobj;
|
||||
|
||||
/** 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 boolean _gameOver;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// $Id: GameControllerDelegate.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 GameControllerDelegate (GameController ctrl)
|
||||
{
|
||||
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 void 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).
|
||||
*/
|
||||
public void gameDidEnd ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game was cancelled for some reason.
|
||||
*/
|
||||
public void 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.
|
||||
*/
|
||||
public void gameWillReset ()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// $Id: GameService.java 3600 2005-06-15 23:46:31Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
|
||||
/**
|
||||
* Provides services used by game clients to request that actions be taken
|
||||
* by the game manager.
|
||||
*/
|
||||
public interface GameService extends InvocationService
|
||||
{
|
||||
/**
|
||||
* Lets the game manager know that the calling player is in the game
|
||||
* room and ready to play.
|
||||
*/
|
||||
public void playerReady (Client client);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// $Id: GameConfigurator.java 3590 2005-06-08 23:20:18Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import com.samskivert.swing.VGroupLayout;
|
||||
|
||||
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}.
|
||||
*/
|
||||
public abstract class SwingGameConfigurator extends GameConfigurator
|
||||
{
|
||||
/**
|
||||
* Get the Swing JPanel that contains the UI elements for this configurator.
|
||||
*/
|
||||
public JPanel getPanel ()
|
||||
{
|
||||
return _panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void addControl (JComponent label, JComponent control)
|
||||
{
|
||||
// Set up the constraints. There's really no point in saving
|
||||
// these somewhere, as they're cloned anyway with every component
|
||||
// insertion.
|
||||
GridBagConstraints lc = new GridBagConstraints();
|
||||
lc.gridx = 0;
|
||||
lc.anchor = GridBagConstraints.NORTHWEST;
|
||||
lc.insets = _labelInsets;
|
||||
|
||||
GridBagConstraints cc = new GridBagConstraints();
|
||||
cc.gridx = 1;
|
||||
cc.anchor = GridBagConstraints.NORTHWEST;
|
||||
cc.insets = _controlInsets;
|
||||
cc.gridwidth = GridBagConstraints.REMAINDER;
|
||||
|
||||
// add the components
|
||||
_panel.add(label, lc);
|
||||
_panel.add(control, cc);
|
||||
}
|
||||
|
||||
/** The panel on which the config options are placed. */
|
||||
protected JPanel _panel = new JPanel(new GridBagLayout());
|
||||
|
||||
/** Insets for configuration labels. */
|
||||
protected Insets _labelInsets = new Insets(1, 0, 1, 4);
|
||||
|
||||
/** Insets for configuration controls. */
|
||||
protected Insets _controlInsets = new Insets(1, 4, 1, 0);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// $Id: GameAI.java 3399 2005-03-12 07:37:34Z mdb $
|
||||
|
||||
package com.threerings.parlor.game.data;
|
||||
|
||||
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 int personality;
|
||||
|
||||
/** The skill level of the AI. */
|
||||
public int skill;
|
||||
|
||||
/** A blank constructor for serialization. */
|
||||
public GameAI ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an AI with the specified (game-interpreted) skill and
|
||||
* personality.
|
||||
*/
|
||||
public GameAI (int personality, int skill)
|
||||
{
|
||||
this.personality = personality;
|
||||
this.skill = skill;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// $Id: PuzzleCodes.java 3184 2004-10-28 19:20:27Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 interface GameCodes extends InvocationCodes
|
||||
{
|
||||
/** The message bundle identifier for general game messages. */
|
||||
public static final String GAME_MESSAGE_BUNDLE = "game.general";
|
||||
|
||||
/** The name of the message event to a placeObject that a player
|
||||
* was knocked out of a puzzle. */
|
||||
public static final String PLAYER_KNOCKED_OUT = "playerKnocked";
|
||||
|
||||
/** The name of the message event to a placeObject that reports
|
||||
* the winners and losers of a game. */
|
||||
public static final String WINNERS_AND_LOSERS = "winnersAndLosers";
|
||||
|
||||
/** A chat type for chatting on the game object. */
|
||||
public static final String GAME_CHAT_TYPE = "gameChat";
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// $Id: GameConfig.java 4026 2006-04-18 01:32:41Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.threerings.crowd.data.PlaceConfig;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
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.
|
||||
*/
|
||||
public abstract class GameConfig extends PlaceConfig implements Cloneable
|
||||
{
|
||||
/** The usernames of the players involved in this game, or an empty
|
||||
* array if such information is not needed by this particular game. */
|
||||
public Name[] players = new Name[0];
|
||||
|
||||
/** Indicates whether or not this game is rated. */
|
||||
public boolean rated = 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 GameAI[] ais = new GameAI[0];
|
||||
|
||||
/**
|
||||
* Returns the message bundle identifier for the bundle that should be
|
||||
* used to translate the translatable strings used to describe the
|
||||
* game config parameters.
|
||||
*/
|
||||
public abstract String getBundleName ();
|
||||
|
||||
/**
|
||||
* 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 GameConfigurator createConfigurator ();
|
||||
|
||||
/**
|
||||
* Creates a table configurator for initializing 'table' properties
|
||||
* of the game. The default implementation returns null.
|
||||
*/
|
||||
public TableConfigurator createTableConfigurator ()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a translatable label describing this game.
|
||||
*/
|
||||
public String getGameName ()
|
||||
{
|
||||
// the whole getRatingTypeId(), getGameName(), getBundleName()
|
||||
// business should be cleaned up. we should have getGameIdent()
|
||||
// and everything should have a default implementation using that
|
||||
return "m." + getBundleName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the game rating type, if the system uses such things.
|
||||
*/
|
||||
public byte getRatingTypeId ()
|
||||
{
|
||||
return (byte)-1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a List of strings that describe the configuration of this
|
||||
* game. Default implementation returns an empty list.
|
||||
*/
|
||||
public List getDescription ()
|
||||
{
|
||||
return new ArrayList(); // nothing by default
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 boolean equals (Object other)
|
||||
{
|
||||
// make sure they're of the same class
|
||||
if (other.getClass() == this.getClass()) {
|
||||
GameConfig that = (GameConfig) other;
|
||||
return this.rated == that.rated;
|
||||
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a hashcode for this game config object that supports our
|
||||
* {@link #equals} implementation. Objects that are equal should have
|
||||
* the same hashcode.
|
||||
*/
|
||||
public int hashCode ()
|
||||
{
|
||||
// look ma, it's so sophisticated!
|
||||
return getClass().hashCode() + (rated ? 1 : 0);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public Object clone ()
|
||||
{
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException cnse) {
|
||||
throw new RuntimeException("clone() failed: " + cnse);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $Id: GameMarshaller.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.game.client.GameService;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.dobj.InvocationResponseEvent;
|
||||
|
||||
/**
|
||||
* Provides the implementation of the {@link GameService} 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 GameMarshaller extends InvocationMarshaller
|
||||
implements GameService
|
||||
{
|
||||
/** The method id used to dispatch {@link #playerReady} requests. */
|
||||
public static final int PLAYER_READY = 1;
|
||||
|
||||
// documentation inherited from interface
|
||||
public void playerReady (Client arg1)
|
||||
{
|
||||
sendRequest(arg1, PLAYER_READY, new Object[] {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
//
|
||||
// $Id: GameObject.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.samskivert.util.ListUtil;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
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>gameService</code> field. */
|
||||
public static final String GAME_SERVICE = "gameService";
|
||||
|
||||
/** The field name of the <code>state</code> field. */
|
||||
public static final String STATE = "state";
|
||||
|
||||
/** The field name of the <code>isRated</code> field. */
|
||||
public static final String IS_RATED = "isRated";
|
||||
|
||||
/** The field name of the <code>isPrivate</code> field. */
|
||||
public static final String IS_PRIVATE = "isPrivate";
|
||||
|
||||
/** The field name of the <code>players</code> field. */
|
||||
public static final String PLAYERS = "players";
|
||||
|
||||
/** The field name of the <code>winners</code> field. */
|
||||
public static final String WINNERS = "winners";
|
||||
|
||||
/** The field name of the <code>roundId</code> field. */
|
||||
public static final String ROUND_ID = "roundId";
|
||||
|
||||
/** The field name of the <code>playerStatus</code> field. */
|
||||
public static final String PLAYER_STATUS = "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 final int PRE_GAME = 0;
|
||||
|
||||
/** A game state constant indicating that the game is in play. */
|
||||
public static final int IN_PLAY = 1;
|
||||
|
||||
/** A game state constant indicating that the game ended normally. */
|
||||
public static final int GAME_OVER = 2;
|
||||
|
||||
/** A game state constant indicating that the game was cancelled. */
|
||||
public static final int CANCELLED = 3;
|
||||
|
||||
/** The player status constant for a player whose game is in play. */
|
||||
public static final int PLAYER_IN_PLAY = 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 final int PLAYER_LEFT_GAME = 1;
|
||||
|
||||
/** Provides general game invocation services. */
|
||||
public GameMarshaller gameService;
|
||||
|
||||
/** The game state, one of {@link #PRE_GAME}, {@link #IN_PLAY},
|
||||
* {@link #GAME_OVER}, or {@link #CANCELLED}. */
|
||||
public int state = PRE_GAME;
|
||||
|
||||
/** Indicates whether or not this game is rated. */
|
||||
public boolean isRated;
|
||||
|
||||
/** Indicates whether the game is "private". */
|
||||
public boolean isPrivate;
|
||||
|
||||
/** The usernames of the players involved in this game. */
|
||||
public Name[] players;
|
||||
|
||||
/** Whether each player in the game is a winner, or <code>null</code>
|
||||
* if the game is not yet over. */
|
||||
public boolean[] winners;
|
||||
|
||||
/** The unique round identifier for the current round. */
|
||||
public int roundId;
|
||||
|
||||
/** 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 int[] playerStatus;
|
||||
|
||||
/**
|
||||
* Returns the number of players in the game.
|
||||
*/
|
||||
public int getPlayerCount ()
|
||||
{
|
||||
int count = 0;
|
||||
int size = players.length;
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
if (players[ii] != null) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of active players in the game.
|
||||
*/
|
||||
public int getActivePlayerCount ()
|
||||
{
|
||||
int count = 0;
|
||||
int size = players.length;
|
||||
for (int ii = 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 boolean isActivePlayer (int pidx)
|
||||
{
|
||||
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 int getPlayerIndex (Name username)
|
||||
{
|
||||
int size = (players == null) ? 0 : players.length;
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
if (players[ii] != null && players[ii].equals(username)) {
|
||||
return ii;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the game is in play. A game that is not in play
|
||||
* could either be awaiting players, ended, or cancelled.
|
||||
*/
|
||||
public boolean isInPlay ()
|
||||
{
|
||||
return (state == IN_PLAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given player index in the game is occupied.
|
||||
*/
|
||||
public boolean isOccupiedPlayer (int pidx)
|
||||
{
|
||||
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 boolean isWinner (int pidx)
|
||||
{
|
||||
return (winners == null) ? false : 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 int getWinnerCount ()
|
||||
{
|
||||
int count = 0;
|
||||
int size = (winners == null) ? 0 : winners.length;
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
if (winners[ii]) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the game is ended in a draw.
|
||||
*/
|
||||
public boolean isDraw ()
|
||||
{
|
||||
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 int getWinnerIndex ()
|
||||
{
|
||||
int size = (winners == null) ? 0 : winners.length;
|
||||
for (int ii = 0; ii < size; ii++) {
|
||||
if (winners[ii]) {
|
||||
return ii;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of party game being played or NOT_PARTY_GAME.
|
||||
* {@link PartyGameConfig}.
|
||||
*/
|
||||
public byte getPartyGameType ()
|
||||
{
|
||||
return PartyGameConfig.NOT_PARTY_GAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 boolean isActivePlayerStatus (int playerStatus)
|
||||
{
|
||||
return playerStatus == PLAYER_IN_PLAY;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
protected void which (StringBuilder buf)
|
||||
{
|
||||
super.which(buf);
|
||||
StringUtil.toString(buf, players);
|
||||
buf.append(":").append(state);
|
||||
}
|
||||
|
||||
// AUTO-GENERATED: METHODS START
|
||||
/**
|
||||
* Requests that the <code>gameService</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 void setGameService (GameMarshaller value)
|
||||
{
|
||||
GameMarshaller ovalue = this.gameService;
|
||||
requestAttributeChange(
|
||||
GAME_SERVICE, value, ovalue);
|
||||
this.gameService = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void setState (int value)
|
||||
{
|
||||
int ovalue = 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 void setIsRated (boolean value)
|
||||
{
|
||||
boolean ovalue = this.isRated;
|
||||
requestAttributeChange(
|
||||
IS_RATED, Boolean.valueOf(value), Boolean.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 void setIsPrivate (boolean value)
|
||||
{
|
||||
boolean ovalue = this.isPrivate;
|
||||
requestAttributeChange(
|
||||
IS_PRIVATE, Boolean.valueOf(value), Boolean.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 void setPlayers (Name[] value)
|
||||
{
|
||||
Name[] ovalue = this.players;
|
||||
requestAttributeChange(
|
||||
PLAYERS, value, ovalue);
|
||||
this.players = (value == null) ? null : (Name[])value.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void setPlayersAt (Name value, int index)
|
||||
{
|
||||
Name ovalue = this.players[index];
|
||||
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 void setWinners (boolean[] value)
|
||||
{
|
||||
boolean[] ovalue = this.winners;
|
||||
requestAttributeChange(
|
||||
WINNERS, value, ovalue);
|
||||
this.winners = (value == null) ? null : (boolean[])value.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void setWinnersAt (boolean value, int index)
|
||||
{
|
||||
boolean ovalue = this.winners[index];
|
||||
requestElementUpdate(
|
||||
WINNERS, index, Boolean.valueOf(value), Boolean.valueOf(ovalue));
|
||||
this.winners[index] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the <code>roundId</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 void setRoundId (int value)
|
||||
{
|
||||
int ovalue = this.roundId;
|
||||
requestAttributeChange(
|
||||
ROUND_ID, Integer.valueOf(value), Integer.valueOf(ovalue));
|
||||
this.roundId = 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 void setPlayerStatus (int[] value)
|
||||
{
|
||||
int[] ovalue = this.playerStatus;
|
||||
requestAttributeChange(
|
||||
PLAYER_STATUS, value, ovalue);
|
||||
this.playerStatus = (value == null) ? null : (int[])value.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 void setPlayerStatusAt (int value, int index)
|
||||
{
|
||||
int ovalue = this.playerStatus[index];
|
||||
requestElementUpdate(
|
||||
PLAYER_STATUS, index, Integer.valueOf(value), Integer.valueOf(ovalue));
|
||||
this.playerStatus[index] = value;
|
||||
}
|
||||
// AUTO-GENERATED: METHODS END
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// $Id: PartyGameConfig.java 3804 2006-01-13 01:52:36Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Provides additional information for party games.
|
||||
* A party game is a game in which the players are not set prior to starting,
|
||||
* but players can come and go at will during the normal progression of
|
||||
* the game.
|
||||
*/
|
||||
public interface PartyGameConfig
|
||||
{
|
||||
/** Party game constant indicating that this game, while it does
|
||||
* implement PartyGameConfig, is not currently being played in party
|
||||
* mode. */
|
||||
public static final byte NOT_PARTY_GAME = 0;
|
||||
|
||||
/** Party game constant indicating that we're in a party game in which
|
||||
* players must sit at an available seat to play, otherwise they're
|
||||
* an observer. */
|
||||
public static final byte SEATED_PARTY_GAME = 1;
|
||||
|
||||
/** Party game constant indicating that everyone in the game place is
|
||||
* a "player", meaning that they do not need to claim a seat to play. */
|
||||
public static final byte FREE_FOR_ALL_PARTY_GAME = 2;
|
||||
|
||||
/**
|
||||
* Get the type of party game being played.
|
||||
*/
|
||||
public byte getPartyGameType ();
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// $Id: AIGameTicker.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.HashSet;
|
||||
|
||||
import com.samskivert.util.Interval;
|
||||
|
||||
import com.threerings.crowd.server.CrowdServer;
|
||||
|
||||
/**
|
||||
* Handles ticking all the GameManagers that are hosting games with AIs.
|
||||
*/
|
||||
public class AIGameTicker extends Interval
|
||||
{
|
||||
/** The frequency with which we dispatch AI game ticks. */
|
||||
public static final long TICK_FREQUENCY = 3333L; // every 3 1/3 seconds
|
||||
|
||||
/**
|
||||
* Register the specified GameManager to receive AI ticks.
|
||||
*/
|
||||
public static synchronized void registerAIGame (GameManager mgr)
|
||||
{
|
||||
if (_ticker == null) {
|
||||
_ticker = new AIGameTicker();
|
||||
}
|
||||
_ticker.addAIGame(mgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take the specified GameManager off the AI tick list.
|
||||
*/
|
||||
public static synchronized void unregisterAIGame (GameManager mgr)
|
||||
{
|
||||
if (_ticker != null) {
|
||||
_ticker.removeAIGame(mgr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an AIGameTicker and start it ticking.
|
||||
*/
|
||||
private AIGameTicker ()
|
||||
{
|
||||
super(CrowdServer.omgr);
|
||||
_games = new HashSet();
|
||||
|
||||
schedule(TICK_FREQUENCY, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the specified manager to the list of those receiving AI ticks.
|
||||
*/
|
||||
protected void addAIGame (GameManager mgr)
|
||||
{
|
||||
_games.add(mgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified manager from receiving AI ticks.
|
||||
*/
|
||||
protected void removeAIGame (GameManager mgr)
|
||||
{
|
||||
_games.remove(mgr);
|
||||
|
||||
// if there aren't any AIs, let's stop running
|
||||
if (_games.isEmpty()) {
|
||||
cancel();
|
||||
_ticker = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tick all the game AIs while on the dobj thread.
|
||||
*/
|
||||
public void expired ()
|
||||
{
|
||||
Iterator iter = _games.iterator();
|
||||
while (iter.hasNext()) {
|
||||
((GameManager) iter.next()).tickAIs();
|
||||
}
|
||||
}
|
||||
|
||||
/** Our set of ai games. */
|
||||
protected HashSet _games;
|
||||
|
||||
/** Our single ticker for all AI games. */
|
||||
protected static AIGameTicker _ticker;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// $Id: GameDispatcher.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.game.client.GameService;
|
||||
import com.threerings.parlor.game.data.GameMarshaller;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.server.InvocationDispatcher;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
|
||||
/**
|
||||
* Dispatches requests to the {@link GameProvider}.
|
||||
*/
|
||||
public class GameDispatcher extends InvocationDispatcher
|
||||
{
|
||||
/**
|
||||
* Creates a dispatcher that may be registered to dispatch invocation
|
||||
* service requests for the specified provider.
|
||||
*/
|
||||
public GameDispatcher (GameProvider provider)
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public InvocationMarshaller createMarshaller ()
|
||||
{
|
||||
return new GameMarshaller();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchRequest (
|
||||
ClientObject source, int methodId, Object[] args)
|
||||
throws InvocationException
|
||||
{
|
||||
switch (methodId) {
|
||||
case GameMarshaller.PLAYER_READY:
|
||||
((GameProvider)provider).playerReady(
|
||||
source
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchRequest(source, methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// $Id: GameManagerDelegate.java 3667 2005-08-03 07:46:54Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.crowd.server.PlaceManagerDelegate;
|
||||
|
||||
import com.threerings.parlor.game.data.GameAI;
|
||||
|
||||
/**
|
||||
* Extends the {@link PlaceManagerDelegate} mechanism with game manager
|
||||
* specific methods.
|
||||
*/
|
||||
public class GameManagerDelegate extends PlaceManagerDelegate
|
||||
{
|
||||
/**
|
||||
* Provides the delegate with a reference to the game manager for
|
||||
* which it is delegating.
|
||||
*/
|
||||
public GameManagerDelegate (GameManager gmgr)
|
||||
{
|
||||
super(gmgr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the game manager when the game is about to start.
|
||||
*/
|
||||
public void gameWillStart ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the game manager after the game was started.
|
||||
*/
|
||||
public void gameDidStart ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player in the game has been replaced by a call to
|
||||
* {@link GameManager#replacePlayer}.
|
||||
*/
|
||||
public void playerWasReplaced (int pidx, Name oldPlayer, Name newPlayer)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the manager when we should do some AI. Only called while
|
||||
* the game is IN_PLAY.
|
||||
*
|
||||
* @param pidx the player index to fake some gameplay for.
|
||||
* @param ai a record indicating the AI's configuration.
|
||||
*/
|
||||
public void tickAI (int pidx, GameAI ai)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the game manager when the game is about to end.
|
||||
*/
|
||||
public void gameWillEnd ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the game manager after the game ended.
|
||||
*/
|
||||
public void gameDidEnd ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game is about to reset, but before any other
|
||||
* clearing out of game data has taken place. Derived classes should
|
||||
* override this if they need to perform some pre-reset activities.
|
||||
*/
|
||||
public void gameWillReset ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the specified player has been set as an AI with the
|
||||
* supplied AI configuration.
|
||||
*/
|
||||
public void setAI (int pidx, GameAI ai)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// $Id: GameProvider.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.game.client.GameService;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationProvider;
|
||||
|
||||
/**
|
||||
* Defines the server-side of the {@link GameService}.
|
||||
*/
|
||||
public interface GameProvider extends InvocationProvider
|
||||
{
|
||||
/**
|
||||
* Handles a {@link GameService#playerReady} request.
|
||||
*/
|
||||
public void playerReady (ClientObject caller);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// $Id: GameWatcher.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.server.PlaceManager;
|
||||
import com.threerings.crowd.server.PlaceRegistry;
|
||||
|
||||
import com.threerings.parlor.game.data.GameObject;
|
||||
|
||||
/**
|
||||
* An abstract convenience class used server-side to keep an eye on a game
|
||||
* and perform a one-time game-over activity when the game ends. Classes
|
||||
* that care to make use of the game watcher should create an instance,
|
||||
* implement {@link #gameDidEnd}, and pass the instance to the place
|
||||
* registry in the call to {@link PlaceRegistry#createPlace} when the
|
||||
* puzzle is created.
|
||||
*/
|
||||
public abstract class GameWatcher
|
||||
implements PlaceRegistry.CreationObserver, AttributeChangeListener
|
||||
{
|
||||
// documentation inherited
|
||||
public void placeCreated (PlaceObject place, PlaceManager pmgr)
|
||||
{
|
||||
_gameobj = (GameObject)place;
|
||||
_gameobj.addListener(this);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void attributeChanged (AttributeChangedEvent event)
|
||||
{
|
||||
if (event.getName().equals(GameObject.STATE)) {
|
||||
// if we transitioned to a non-in-play state, the game has
|
||||
// completed
|
||||
if (!_gameobj.isInPlay()) {
|
||||
try {
|
||||
gameDidEnd(_gameobj);
|
||||
} finally {
|
||||
_gameobj.removeListener(this);
|
||||
_gameobj = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the game ends to give derived classes a chance to
|
||||
* engage in their game-over antics.
|
||||
*/
|
||||
protected abstract void gameDidEnd (GameObject gameobj);
|
||||
|
||||
/** The game object we're observing. */
|
||||
protected GameObject _gameobj;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
/**
|
||||
* An interface to be implemented by a game if it wants to hear about
|
||||
* the team indices that were configured during matchmaking.
|
||||
*/
|
||||
public interface TeamGameManager
|
||||
{
|
||||
/**
|
||||
* Set the team member indices. For example, a game with
|
||||
* three players in two teams- players 0 and 2 versus player 1- would
|
||||
* have { {0, 2}, {1} } set.
|
||||
*/
|
||||
public void setTeamMemberIndices (int[][] teams);
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// $Id: ScoreAnimation.java 3479 2005-04-13 19:06:33Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.media;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
|
||||
import com.samskivert.swing.Label;
|
||||
|
||||
import com.threerings.media.MediaPanel;
|
||||
import com.threerings.media.animation.FloatingTextAnimation;
|
||||
|
||||
public class ScoreAnimation extends FloatingTextAnimation
|
||||
{
|
||||
{ // initializer, run automatically with every constructor
|
||||
setRenderOrder(Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a score animation for the given score value centered at
|
||||
* the given coordinates.
|
||||
*/
|
||||
public ScoreAnimation (Label label, int x, int y)
|
||||
{
|
||||
super(label, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a score animation for the given score value centered at
|
||||
* the given coordinates. The animation will float up the screen for
|
||||
* 30 pixels.
|
||||
*/
|
||||
public ScoreAnimation (Label label, int x, int y, long floatPeriod)
|
||||
{
|
||||
super(label, x, y, floatPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a score animation for the given score value starting at
|
||||
* the given coordinates and floating toward the specified
|
||||
* coordinates.
|
||||
*/
|
||||
public ScoreAnimation (Label label, int sx, int sy,
|
||||
int destx, int desty, long floatPeriod)
|
||||
{
|
||||
super(label, sx, sy, destx, desty, floatPeriod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and configure a Label suitable for a ScoreAnimation with
|
||||
* all the most common options.
|
||||
*/
|
||||
public static Label createLabel (String score, Color c, Font font,
|
||||
MediaPanel host)
|
||||
{
|
||||
Label label = new Label(score);
|
||||
label.setTargetWidth(host.getWidth());
|
||||
label.setStyle(Label.OUTLINE);
|
||||
label.setTextColor(c);
|
||||
label.setAlternateColor(Color.BLACK);
|
||||
label.setFont(font);
|
||||
label.setAlignment(Label.CENTER);
|
||||
label.layout(host);
|
||||
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
//
|
||||
// $Id: ParlorDispatcher.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.client.ParlorService;
|
||||
import com.threerings.parlor.data.ParlorMarshaller;
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.presents.client.Client;
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.data.InvocationMarshaller;
|
||||
import com.threerings.presents.server.InvocationDispatcher;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Dispatches requests to the {@link ParlorProvider}.
|
||||
*/
|
||||
public class ParlorDispatcher extends InvocationDispatcher
|
||||
{
|
||||
/**
|
||||
* Creates a dispatcher that may be registered to dispatch invocation
|
||||
* service requests for the specified provider.
|
||||
*/
|
||||
public ParlorDispatcher (ParlorProvider provider)
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public InvocationMarshaller createMarshaller ()
|
||||
{
|
||||
return new ParlorMarshaller();
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void dispatchRequest (
|
||||
ClientObject source, int methodId, Object[] args)
|
||||
throws InvocationException
|
||||
{
|
||||
switch (methodId) {
|
||||
case ParlorMarshaller.CANCEL:
|
||||
((ParlorProvider)provider).cancel(
|
||||
source,
|
||||
((Integer)args[0]).intValue(), (InvocationService.InvocationListener)args[1]
|
||||
);
|
||||
return;
|
||||
|
||||
case ParlorMarshaller.CREATE_TABLE:
|
||||
((ParlorProvider)provider).createTable(
|
||||
source,
|
||||
((Integer)args[0]).intValue(), (TableConfig)args[1], (GameConfig)args[2], (ParlorService.TableListener)args[3]
|
||||
);
|
||||
return;
|
||||
|
||||
case ParlorMarshaller.INVITE:
|
||||
((ParlorProvider)provider).invite(
|
||||
source,
|
||||
(Name)args[0], (GameConfig)args[1], (ParlorService.InviteListener)args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
case ParlorMarshaller.JOIN_TABLE:
|
||||
((ParlorProvider)provider).joinTable(
|
||||
source,
|
||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), ((Integer)args[2]).intValue(), (InvocationService.InvocationListener)args[3]
|
||||
);
|
||||
return;
|
||||
|
||||
case ParlorMarshaller.LEAVE_TABLE:
|
||||
((ParlorProvider)provider).leaveTable(
|
||||
source,
|
||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (InvocationService.InvocationListener)args[2]
|
||||
);
|
||||
return;
|
||||
|
||||
case ParlorMarshaller.RESPOND:
|
||||
((ParlorProvider)provider).respond(
|
||||
source,
|
||||
((Integer)args[0]).intValue(), ((Integer)args[1]).intValue(), (Object)args[2], (InvocationService.InvocationListener)args[3]
|
||||
);
|
||||
return;
|
||||
|
||||
case ParlorMarshaller.START_SOLITAIRE:
|
||||
((ParlorProvider)provider).startSolitaire(
|
||||
source,
|
||||
(GameConfig)args[0], (InvocationService.ConfirmListener)args[1]
|
||||
);
|
||||
return;
|
||||
|
||||
default:
|
||||
super.dispatchRequest(source, methodId, args);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
//
|
||||
// $Id: ParlorManager.java 3758 2005-11-10 23:18:58Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationManager;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.server.PlaceRegistry;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
|
||||
/**
|
||||
* The parlor manager is responsible for the parlor services in
|
||||
* aggregate. This includes maintaining the registry of active games,
|
||||
* handling the necessary coordination for the matchmaking services and
|
||||
* anything else that falls outside the scope of an actual in-progress
|
||||
* game.
|
||||
*/
|
||||
public class ParlorManager
|
||||
implements ParlorCodes
|
||||
{
|
||||
/** Provides the server-side implementation of the parlor services. */
|
||||
public ParlorProvider parprov;
|
||||
|
||||
/**
|
||||
* Initializes the parlor manager. This should be called by the server
|
||||
* that is making use of the parlor services on the single instance of
|
||||
* parlor manager that it has created.
|
||||
*
|
||||
* @param invmgr a reference to the invocation manager in use by this
|
||||
* server.
|
||||
* @param plreg a reference to the place registry to be used by the
|
||||
* parlor manager when creating game places.
|
||||
*/
|
||||
public void init (InvocationManager invmgr, PlaceRegistry plreg)
|
||||
{
|
||||
// create and register our invocation provider
|
||||
parprov = new ParlorProvider(this);
|
||||
invmgr.registerDispatcher(new ParlorDispatcher(parprov), true);
|
||||
|
||||
// keep this for later
|
||||
_plreg = plreg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an invitation from the <code>inviter</code> to the
|
||||
* <code>invitee</code> for a game as described by the supplied config
|
||||
* object.
|
||||
*
|
||||
* @param inviter the player initiating the invitation.
|
||||
* @param invitee the player being invited.
|
||||
* @param config the configuration of the game being proposed.
|
||||
*
|
||||
* @return the invitation identifier for the newly created invitation
|
||||
* record.
|
||||
*
|
||||
* @exception InvocationException thrown if the invitation was not
|
||||
* able to be processed for some reason (like the invited player has
|
||||
* requested not to be disturbed). The explanation will be provided in
|
||||
* the message data of the exception.
|
||||
*/
|
||||
public int invite (BodyObject inviter, BodyObject invitee,
|
||||
GameConfig config)
|
||||
throws InvocationException
|
||||
{
|
||||
// Log.info("Received invitation request [inviter=" + inviter +
|
||||
// ", invitee=" + invitee + ", config=" + config + "].");
|
||||
|
||||
// here we should check to make sure the invitee hasn't muted the
|
||||
// inviter, and that the inviter isn't shunned and all that other
|
||||
// access control type stuff
|
||||
|
||||
// create a new invitation record for this invitation
|
||||
Invitation invite = new Invitation(inviter, invitee, config);
|
||||
|
||||
// stick it in the pending invites table
|
||||
_invites.put(invite.inviteId, invite);
|
||||
|
||||
// deliver an invite notification to the invitee
|
||||
ParlorSender.sendInvite(
|
||||
invitee, invite.inviteId, inviter.getVisibleName(), config);
|
||||
|
||||
// and let the caller know the invite id we assigned
|
||||
return invite.inviteId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Effects a response to an invitation (accept, refuse or counter),
|
||||
* made by the specified source user with the specified arguments.
|
||||
*
|
||||
* @param source the body object of the user that is issuing this
|
||||
* response.
|
||||
* @param inviteId the identifier of the invitation to which we are
|
||||
* responding.
|
||||
* @param code the response code (either {@link
|
||||
* #INVITATION_ACCEPTED}, {@link #INVITATION_REFUSED} or {@link
|
||||
* #INVITATION_COUNTERED}).
|
||||
* @param arg the argument that goes along with the response: an
|
||||
* explanatory message in the case of a refusal (the empty string, not
|
||||
* null, if no message was provided) or the new game configuration in
|
||||
* the case of a counter-invitation.
|
||||
*/
|
||||
public void respondToInvite (BodyObject source, int inviteId, int code,
|
||||
Object arg)
|
||||
{
|
||||
// look up the invitation
|
||||
Invitation invite = (Invitation)_invites.get(inviteId);
|
||||
if (invite == null) {
|
||||
Log.warning("Requested to respond to non-existent invitation " +
|
||||
"[source=" + source + ", inviteId=" + inviteId +
|
||||
", code=" + code + ", arg=" + arg + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure this response came from the proper person
|
||||
if (source != invite.invitee) {
|
||||
Log.warning("Got response from non-invitee [source=" + source +
|
||||
", invite=" + invite + ", code=" + code +
|
||||
", arg=" + arg + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// let the other user know that a response was made to this
|
||||
// invitation
|
||||
ParlorSender.sendInviteResponse(
|
||||
invite.inviter, invite.inviteId, code, arg);
|
||||
|
||||
switch (code) {
|
||||
case INVITATION_ACCEPTED:
|
||||
// the invitation was accepted, so we'll need to start up the
|
||||
// game and get the necessary balls rolling
|
||||
processAcceptedInvitation(invite);
|
||||
// and remove the invitation from the pending table
|
||||
_invites.remove(inviteId);
|
||||
break;
|
||||
|
||||
case INVITATION_REFUSED:
|
||||
// remove the invitation record from the pending table as it
|
||||
// is no longer pending
|
||||
_invites.remove(inviteId);
|
||||
break;
|
||||
|
||||
case INVITATION_COUNTERED:
|
||||
// swap control of the invitation to the invitee
|
||||
invite.swapControl();
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.warning("Requested to respond to invitation with " +
|
||||
"unknown response code [source=" + source +
|
||||
", invite=" + invite + ", code=" + code +
|
||||
", arg=" + arg + "].");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that an outstanding invitation be cancelled.
|
||||
*
|
||||
* @param source the body object of the user that is making the
|
||||
* request.
|
||||
* @param inviteId the unique id of the invitation to be cancelled.
|
||||
*/
|
||||
public void cancelInvite (BodyObject source, int inviteId)
|
||||
{
|
||||
// TBD
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts up and configures the game manager for an accepted
|
||||
* invitation.
|
||||
*/
|
||||
protected void processAcceptedInvitation (Invitation invite)
|
||||
{
|
||||
try {
|
||||
Log.info("Creating game manager [invite=" + invite + "].");
|
||||
|
||||
// configure the game config with the player info
|
||||
invite.config.players = new Name[] {
|
||||
invite.invitee.username, invite.inviter.username };
|
||||
|
||||
// create the game manager and begin it's initialization
|
||||
// process. the game manager will take care of notifying the
|
||||
// players that the game has been created once it has been
|
||||
// started up (which is done by the place registry once the
|
||||
// game object creation has completed)
|
||||
GameManager gmgr = (GameManager)
|
||||
_plreg.createPlace(invite.config, null);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.warning("Unable to create game manager [invite=" + invite +
|
||||
", error=" + e + "].");
|
||||
Log.logStackTrace(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The invitation record is used by the parlor manager to keep track
|
||||
* of pending invitations.
|
||||
*/
|
||||
protected static class Invitation
|
||||
{
|
||||
/** The unique identifier for this invitation. */
|
||||
public int inviteId = _nextInviteId++;
|
||||
|
||||
/** The person proposing the invitation. */
|
||||
public BodyObject inviter;
|
||||
|
||||
/** The person to whom the invitation is proposed. */
|
||||
public BodyObject invitee;
|
||||
|
||||
/** The configuration of the game being proposed. */
|
||||
public GameConfig config;
|
||||
|
||||
/**
|
||||
* Constructs a new invitation with the specified participants and
|
||||
* configuration.
|
||||
*/
|
||||
public Invitation (BodyObject inviter, BodyObject invitee,
|
||||
GameConfig config)
|
||||
{
|
||||
this.inviter = inviter;
|
||||
this.invitee = invitee;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swaps the inviter and invitee which is necessary when the
|
||||
* invitee responds with a counter-invitation.
|
||||
*/
|
||||
public void swapControl ()
|
||||
{
|
||||
BodyObject tmp = inviter;
|
||||
inviter = invitee;
|
||||
invitee = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/** The place registry with which we operate. */
|
||||
protected PlaceRegistry _plreg;
|
||||
|
||||
/** The table of pending invitations. */
|
||||
protected HashIntMap _invites = new HashIntMap();
|
||||
|
||||
/** A counter used to generate unique identifiers for invitation
|
||||
* records. */
|
||||
protected static int _nextInviteId = 0;
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
//
|
||||
// $Id: ParlorProvider.java 3758 2005-11-10 23:18:58Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.client.InvocationService;
|
||||
import com.threerings.presents.client.InvocationService.InvocationListener;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
import com.threerings.presents.server.InvocationProvider;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.server.CrowdServer;
|
||||
import com.threerings.crowd.server.PlaceManager;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.client.ParlorService;
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
import com.threerings.parlor.data.TableConfig;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
|
||||
/**
|
||||
* The parlor provider handles the server side of the various Parlor
|
||||
* services that are made available for direct invocation by the client.
|
||||
* Primarily these are the matchmaking mechanisms.
|
||||
*/
|
||||
public class ParlorProvider
|
||||
implements InvocationProvider, ParlorCodes
|
||||
{
|
||||
/**
|
||||
* Constructs a parlor provider instance which will be used to handle
|
||||
* all parlor-related invocation service requests. This is
|
||||
* automatically taken care of by the parlor manager, so no other
|
||||
* entity need instantiate and register a parlor provider.
|
||||
*
|
||||
* @param pmgr a reference to the parlor manager active in this
|
||||
* server.
|
||||
*/
|
||||
public ParlorProvider (ParlorManager pmgr)
|
||||
{
|
||||
_pmgr = pmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from the client to invite another user to play
|
||||
* a game.
|
||||
*/
|
||||
public void invite (ClientObject caller, Name invitee, GameConfig config,
|
||||
ParlorService.InviteListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
// Log.info("Handling invite request [source=" + source +
|
||||
// ", invitee=" + invitee + ", config=" + config + "].");
|
||||
|
||||
BodyObject source = (BodyObject)caller;
|
||||
String rsp = null;
|
||||
|
||||
// ensure that the invitee is online at present
|
||||
BodyObject target = CrowdServer.lookupBody(invitee);
|
||||
if (target == null) {
|
||||
throw new InvocationException(INVITEE_NOT_ONLINE);
|
||||
}
|
||||
|
||||
// submit the invite request to the parlor manager
|
||||
int inviteId = _pmgr.invite(source, target, config);
|
||||
listener.inviteReceived(inviteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from the client to respond to an outstanding
|
||||
* invitation by accepting, refusing, or countering it.
|
||||
*/
|
||||
public void respond (ClientObject caller, int inviteId, int code,
|
||||
Object arg, InvocationListener listener)
|
||||
{
|
||||
// pass this on to the parlor manager
|
||||
_pmgr.respondToInvite((BodyObject)caller, inviteId, code, arg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from the client to cancel an outstanding
|
||||
* invitation.
|
||||
*/
|
||||
public void cancel (ClientObject caller, int inviteId,
|
||||
InvocationListener listener)
|
||||
{
|
||||
// pass this on to the parlor manager
|
||||
_pmgr.cancelInvite((BodyObject)caller, inviteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from the client to create a new table.
|
||||
*/
|
||||
public void createTable (
|
||||
ClientObject caller, int lobbyOid, TableConfig tableConfig,
|
||||
GameConfig config, ParlorService.TableListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
Log.info("Handling create table request [caller=" + caller.who() +
|
||||
", lobbyOid=" + lobbyOid + ", config=" + config + "].");
|
||||
|
||||
// pass the creation request on to the table manager
|
||||
TableManager tmgr = getTableManager(lobbyOid);
|
||||
int tableId = tmgr.createTable((BodyObject)caller, tableConfig, config);
|
||||
listener.tableCreated(tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from the client to join an existing table.
|
||||
*/
|
||||
public void joinTable (ClientObject caller, int lobbyOid, int tableId,
|
||||
int position, InvocationListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
Log.info("Handling join table request [caller=" + caller.who() +
|
||||
", lobbyOid=" + lobbyOid + ", tableId=" + tableId +
|
||||
", position=" + position + "].");
|
||||
|
||||
// pass the join request on to the table manager
|
||||
TableManager tmgr = getTableManager(lobbyOid);
|
||||
tmgr.joinTable((BodyObject)caller, tableId, position);
|
||||
|
||||
// there is normally no success response. the client will see
|
||||
// themselves show up in the table that they joined
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a request from the client to leave an existing table.
|
||||
*/
|
||||
public void leaveTable (ClientObject caller, int lobbyOid, int tableId,
|
||||
InvocationListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
Log.info("Handling leave table request [caller=" + caller.who() +
|
||||
", lobbyOid=" + lobbyOid + ", tableId=" + tableId + "].");
|
||||
|
||||
// pass the join request on to the table manager
|
||||
TableManager tmgr = getTableManager(lobbyOid);
|
||||
tmgr.leaveTable((BodyObject)caller, tableId);
|
||||
|
||||
// there is normally no success response. the client will see
|
||||
// themselves removed from the table they just left
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a {@link ParlorService#startSolitaire} request.
|
||||
*/
|
||||
public void startSolitaire (ClientObject caller, GameConfig config,
|
||||
InvocationService.ConfirmListener listener)
|
||||
throws InvocationException
|
||||
{
|
||||
BodyObject user = (BodyObject)caller;
|
||||
|
||||
Log.debug("Processing start puzzle [caller=" + user.who() +
|
||||
", config=" + config + "].");
|
||||
|
||||
try {
|
||||
// just this fellow will be playing
|
||||
if (config.players == null || config.players.length == 0) {
|
||||
config.players = new Name[] { user.getVisibleName() };
|
||||
}
|
||||
|
||||
// create the game manager and begin its initialization
|
||||
// process
|
||||
GameManager gmgr = (GameManager)
|
||||
CrowdServer.plreg.createPlace(config, null);
|
||||
|
||||
// the game manager will take care of notifying the player
|
||||
// that the game has been created once it has been started up;
|
||||
// but we let the caller know that we processed their request
|
||||
listener.requestProcessed();
|
||||
|
||||
} catch (InstantiationException ie) {
|
||||
Log.warning("Error instantiating game manager " +
|
||||
"[for=" + caller.who() + ", config=" + config + "].");
|
||||
Log.logStackTrace(ie);
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up the place manager associated with the supplied lobby oid,
|
||||
* casts it to a table lobby manager and obtains the associated table
|
||||
* manager reference.
|
||||
*
|
||||
* @exception InvocationException thrown if something goes wrong
|
||||
* along the way like no place manager exists or the place manager
|
||||
* that does exist doesn't implement table lobby manager.
|
||||
*/
|
||||
protected TableManager getTableManager (int lobbyOid)
|
||||
throws InvocationException
|
||||
{
|
||||
PlaceManager plmgr = CrowdServer.plreg.getPlaceManager(lobbyOid);
|
||||
if (plmgr == null) {
|
||||
Log.warning("No place manager exists from which to obtain " +
|
||||
"table manager reference [ploid=" + lobbyOid + "].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
// sanity check
|
||||
if (!(plmgr instanceof TableManagerProvider)) {
|
||||
Log.warning("Place manager not a table lobby manager " +
|
||||
"[plmgr=" + plmgr + "].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
return ((TableManagerProvider)plmgr).getTableManager();
|
||||
}
|
||||
|
||||
/** A reference to the parlor manager we're working with. */
|
||||
protected ParlorManager _pmgr;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// $Id: ParlorSender.java 4145 2006-05-24 01:24:24Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.parlor.client.ParlorDecoder;
|
||||
import com.threerings.parlor.client.ParlorReceiver;
|
||||
import com.threerings.parlor.game.data.GameConfig;
|
||||
import com.threerings.presents.data.ClientObject;
|
||||
import com.threerings.presents.server.InvocationSender;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
/**
|
||||
* Used to issue notifications to a {@link ParlorReceiver} instance on a
|
||||
* client.
|
||||
*/
|
||||
public class ParlorSender extends InvocationSender
|
||||
{
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* ParlorReceiver#gameIsReady} on a client.
|
||||
*/
|
||||
public static void gameIsReady (
|
||||
ClientObject target, int arg1)
|
||||
{
|
||||
sendNotification(
|
||||
target, ParlorDecoder.RECEIVER_CODE, ParlorDecoder.GAME_IS_READY,
|
||||
new Object[] { Integer.valueOf(arg1) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* ParlorReceiver#receivedInvite} on a client.
|
||||
*/
|
||||
public static void sendInvite (
|
||||
ClientObject target, int arg1, Name arg2, GameConfig arg3)
|
||||
{
|
||||
sendNotification(
|
||||
target, ParlorDecoder.RECEIVER_CODE, ParlorDecoder.RECEIVED_INVITE,
|
||||
new Object[] { Integer.valueOf(arg1), arg2, arg3 });
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* ParlorReceiver#receivedInviteCancellation} on a client.
|
||||
*/
|
||||
public static void sendInviteCancellation (
|
||||
ClientObject target, int arg1)
|
||||
{
|
||||
sendNotification(
|
||||
target, ParlorDecoder.RECEIVER_CODE, ParlorDecoder.RECEIVED_INVITE_CANCELLATION,
|
||||
new Object[] { Integer.valueOf(arg1) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues a notification that will result in a call to {@link
|
||||
* ParlorReceiver#receivedInviteResponse} on a client.
|
||||
*/
|
||||
public static void sendInviteResponse (
|
||||
ClientObject target, int arg1, int arg2, Object arg3)
|
||||
{
|
||||
sendNotification(
|
||||
target, ParlorDecoder.RECEIVER_CODE, ParlorDecoder.RECEIVED_INVITE_RESPONSE,
|
||||
new Object[] { Integer.valueOf(arg1), Integer.valueOf(arg2), arg3 });
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
//
|
||||
// $Id: TableManager.java 3804 2006-01-13 01:52:36Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.samskivert.util.HashIntMap;
|
||||
import com.samskivert.util.StringUtil;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.presents.dobj.ChangeListener;
|
||||
import com.threerings.presents.dobj.ObjectAddedEvent;
|
||||
import com.threerings.presents.dobj.ObjectDeathListener;
|
||||
import com.threerings.presents.dobj.ObjectDestroyedEvent;
|
||||
import com.threerings.presents.dobj.ObjectRemovedEvent;
|
||||
import com.threerings.presents.dobj.OidListListener;
|
||||
import com.threerings.presents.server.InvocationException;
|
||||
|
||||
import com.threerings.crowd.data.BodyObject;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
import com.threerings.crowd.server.CrowdServer;
|
||||
import com.threerings.crowd.server.PlaceManager;
|
||||
import com.threerings.crowd.server.PlaceRegistry;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.data.ParlorCodes;
|
||||
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.game.data.GameObject;
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
|
||||
/**
|
||||
* A table manager can be used by a place manager to take care of the
|
||||
* management of a table matchmaking service in the place managed by the
|
||||
* place manager. The place manager need instantiate a table manager and
|
||||
* implement the {@link TableManagerProvider} interface to provide access
|
||||
* to the table manager for the associated invocation services.
|
||||
*/
|
||||
public class TableManager
|
||||
implements ParlorCodes, OidListListener
|
||||
{
|
||||
/**
|
||||
* Creates a table manager that will work in tandem with the specified
|
||||
* place manager to manage a table matchmaking service in this place.
|
||||
*/
|
||||
public TableManager (PlaceManager plmgr)
|
||||
{
|
||||
// get a reference to our place object
|
||||
_plobj = plmgr.getPlaceObject();
|
||||
|
||||
// add ourselves as an oidlist listener to this lobby so that we
|
||||
// can tell if a user leaves the lobby without leaving their table
|
||||
_plobj.addListener(this);
|
||||
|
||||
// make sure it implements table lobby object
|
||||
_tlobj = (TableLobbyObject)_plobj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that a new table be created to matchmake the game
|
||||
* described by the supplied game config instance. The config instance
|
||||
* provided must implement the {@link TableConfig} interface so that
|
||||
* the parlor services can determine how to configure the table that
|
||||
* will be created.
|
||||
*
|
||||
* @param creator the body object that will own the new table.
|
||||
* @param tableConfig the configuration parameters for the table.
|
||||
* @param config the configuration of the game to be created.
|
||||
*
|
||||
* @return the id of the newly created table.
|
||||
*
|
||||
* @exception InvocationException thrown if the table creation was
|
||||
* not able processed for some reason. The explanation will be
|
||||
* provided in the message data of the exception.
|
||||
*/
|
||||
public int createTable (BodyObject creator, TableConfig tableConfig,
|
||||
GameConfig config)
|
||||
throws InvocationException
|
||||
{
|
||||
// make sure the creator is an occupant of the lobby in which
|
||||
// they are requesting to create a table
|
||||
if (!_plobj.occupants.contains(creator.getOid())) {
|
||||
Log.warning("Requested to create a table in a lobby not " +
|
||||
"occupied by the creator [creator=" + creator +
|
||||
", loboid=" + _plobj.getOid() + "].");
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
|
||||
// create a brand spanking new table
|
||||
Table table = new Table(_plobj.getOid(), tableConfig, config);
|
||||
|
||||
// stick the creator into the first non-AI position
|
||||
int cpos = (config.ais == null) ? 0 : config.ais.length;
|
||||
String error = table.setOccupant(cpos, creator);
|
||||
if (error != null) {
|
||||
Log.warning("Unable to add creator to position zero of " +
|
||||
"table!? [table=" + table + ", creator=" + creator +
|
||||
", error=" + error + "].");
|
||||
// bail out now and abort the table creation process
|
||||
throw new InvocationException(error);
|
||||
}
|
||||
|
||||
// stick the table into the table lobby object
|
||||
_tlobj.addToTables(table);
|
||||
|
||||
// make a mapping from the creator to this table
|
||||
_boidMap.put(creator.getOid(), table);
|
||||
|
||||
// also stick it into our tables tables
|
||||
_tables.put(table.getTableId(), table);
|
||||
|
||||
// if the table has only one seat, start the game immediately
|
||||
if (table.shouldBeStarted()) {
|
||||
createGame(table);
|
||||
}
|
||||
|
||||
// finally let the caller know what the new table id is
|
||||
return table.getTableId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified user be added to the specified table at
|
||||
* the specified position. If the user successfully joins the table,
|
||||
* the function will return normally. If they are not able to join for
|
||||
* some reason (the slot is already full, etc.), a {@link
|
||||
* InvocationException} will be thrown with a message code that
|
||||
* describes the reason for failure. If the user does successfully
|
||||
* join, they will be added to the table entry in the tables set in
|
||||
* the place object that is hosting the table.
|
||||
*
|
||||
* @param joiner the body object of the user that wishes to join the
|
||||
* table.
|
||||
* @param tableId the id of the table to be joined.
|
||||
* @param position the position at which to join the table.
|
||||
*
|
||||
* @exception InvocationException thrown if the joining was not able
|
||||
* processed for some reason. The explanation will be provided in the
|
||||
* message data of the exception.
|
||||
*/
|
||||
public void joinTable (BodyObject joiner, int tableId, int position)
|
||||
throws InvocationException
|
||||
{
|
||||
// look the table up
|
||||
Table table = (Table)_tables.get(tableId);
|
||||
if (table == null) {
|
||||
throw new InvocationException(NO_SUCH_TABLE);
|
||||
}
|
||||
|
||||
// request that the user be added to the table at that position
|
||||
String error = table.setOccupant(position, joiner);
|
||||
// if that failed, report the error
|
||||
if (error != null) {
|
||||
throw new InvocationException(error);
|
||||
}
|
||||
|
||||
// if the table is sufficiently full, start the game automatically
|
||||
if (table.shouldBeStarted()) {
|
||||
createGame(table);
|
||||
} else {
|
||||
// make a mapping from this occupant to this table
|
||||
_boidMap.put(joiner.getOid(), table);
|
||||
}
|
||||
|
||||
// update the table in the lobby
|
||||
_tlobj.updateTables(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the specified user be removed from the specified
|
||||
* table. If the user successfully leaves the table, the function will
|
||||
* return normally. If they are not able to leave for some reason
|
||||
* (they aren't sitting at the table, etc.), a {@link
|
||||
* InvocationException} will be thrown with a message code that
|
||||
* describes the reason for failure.
|
||||
*
|
||||
* @param leaver the body object of the user that wishes to leave the
|
||||
* table.
|
||||
* @param tableId the id of the table to be left.
|
||||
*
|
||||
* @exception InvocationException thrown if the leaving was not able
|
||||
* processed for some reason. The explanation will be provided in the
|
||||
* message data of the exception.
|
||||
*/
|
||||
public void leaveTable (BodyObject leaver, int tableId)
|
||||
throws InvocationException
|
||||
{
|
||||
// look the table up
|
||||
Table table = (Table)_tables.get(tableId);
|
||||
if (table == null) {
|
||||
throw new InvocationException(NO_SUCH_TABLE);
|
||||
}
|
||||
|
||||
// request that the user be removed from the table
|
||||
if (!table.clearOccupant(leaver.getVisibleName())) {
|
||||
throw new InvocationException(NOT_AT_TABLE);
|
||||
}
|
||||
|
||||
// remove the mapping from this user to the table
|
||||
if (_boidMap.remove(leaver.getOid()) == null) {
|
||||
Log.warning("No body to table mapping to clear? " +
|
||||
"[leaver=" + leaver + ", table=" + table + "].");
|
||||
}
|
||||
|
||||
// either update or delete the table depending on whether or not
|
||||
// we just removed the last occupant
|
||||
if (table.isEmpty()) {
|
||||
purgeTable(table);
|
||||
} else {
|
||||
_tlobj.updateTables(table);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the table from all of our internal tables and from its
|
||||
* lobby's distributed object.
|
||||
*/
|
||||
protected void purgeTable (Table table)
|
||||
{
|
||||
// remove the table from our tables table
|
||||
_tables.remove(table.getTableId());
|
||||
|
||||
// clear out all matching entries in the boid map
|
||||
for (int i = 0; i < table.bodyOids.length; i++) {
|
||||
_boidMap.remove(table.bodyOids[i]);
|
||||
}
|
||||
|
||||
// remove the table from the lobby object
|
||||
_tlobj.removeFromTables(table.tableId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we're ready to create a game (either an invitation has
|
||||
* been accepted or a table is ready to start. If there is a problem
|
||||
* creating the game manager, it should be reported in the logs.
|
||||
*/
|
||||
protected void createGame (final Table table)
|
||||
throws InvocationException
|
||||
{
|
||||
// fill the players array into the game config
|
||||
table.config.players = table.getPlayers();
|
||||
|
||||
PlaceRegistry.CreationObserver obs =
|
||||
new PlaceRegistry.CreationObserver() {
|
||||
public void placeCreated (PlaceObject plobj, PlaceManager pmgr) {
|
||||
gameCreated(table, plobj);
|
||||
}
|
||||
};
|
||||
try {
|
||||
CrowdServer.plreg.createPlace(table.config, obs);
|
||||
} catch (Throwable t) {
|
||||
Log.warning("Failed to create manager for game " +
|
||||
"[config=" + table.config + "]: " + t);
|
||||
throw new InvocationException(INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when our game has been created, we take this opportunity to
|
||||
* clean up the table and transition it to "in play" mode.
|
||||
*/
|
||||
protected void gameCreated (Table table, PlaceObject plobj)
|
||||
{
|
||||
// update the table with the newly created game object
|
||||
table.gameOid = plobj.getOid();
|
||||
|
||||
// configure the privacy of the game
|
||||
((GameObject) plobj).setIsPrivate(table.tconfig.privateTable);
|
||||
|
||||
// clear the occupant to table mappings as this game is underway
|
||||
for (int i = 0; i < table.bodyOids.length; i++) {
|
||||
_boidMap.remove(table.bodyOids[i]);
|
||||
}
|
||||
|
||||
// add an object death listener to unmap the table when the game
|
||||
// finally goes away
|
||||
plobj.addListener(_gameDeathListener);
|
||||
|
||||
// and then update the lobby object that contains the table
|
||||
_tlobj.updateTables(table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a game created from a table managed by this table
|
||||
* manager was destroyed. We remove the associated table.
|
||||
*/
|
||||
protected void unmapTable (int gameOid)
|
||||
{
|
||||
// look through our tables table for a table with a matching game
|
||||
Iterator iter = _tables.values().iterator();
|
||||
while (iter.hasNext()) {
|
||||
Table table = (Table)iter.next();
|
||||
if (table.gameOid == gameOid) {
|
||||
purgeTable(table);
|
||||
return; // all done
|
||||
}
|
||||
}
|
||||
|
||||
Log.warning("Requested to unmap table that wasn't mapped " +
|
||||
"[gameOid=" + gameOid + "].");
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void objectAdded (ObjectAddedEvent event)
|
||||
{
|
||||
// nothing doing
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void objectRemoved (ObjectRemovedEvent event)
|
||||
{
|
||||
// if an occupant departed, see if they are in a pending table
|
||||
if (!event.getName().equals(PlaceObject.OCCUPANTS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// look up the table to which this occupant is mapped
|
||||
int bodyOid = event.getOid();
|
||||
Table pender = (Table)_boidMap.remove(bodyOid);
|
||||
if (pender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// remove this occupant from the table
|
||||
if (!pender.clearOccupant(bodyOid)) {
|
||||
Log.warning("Attempt to remove body from mapped table failed " +
|
||||
"[table=" + pender + ", bodyOid=" + bodyOid + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// either update or delete the table depending on whether or not
|
||||
// we just removed the last occupant
|
||||
if (pender.isEmpty()) {
|
||||
purgeTable(pender);
|
||||
} else {
|
||||
_tlobj.updateTables(pender);
|
||||
}
|
||||
}
|
||||
|
||||
/** A reference to the place object in which we're managing tables. */
|
||||
protected PlaceObject _plobj;
|
||||
|
||||
/** A reference to our place object casted to a table lobby object. */
|
||||
protected TableLobbyObject _tlobj;
|
||||
|
||||
/** The table of pending tables. */
|
||||
protected HashIntMap _tables = new HashIntMap();
|
||||
|
||||
/** A mapping from body oid to table. */
|
||||
protected HashIntMap _boidMap = new HashIntMap();
|
||||
|
||||
/** A listener that prunes tables after the game dies. */
|
||||
protected ChangeListener _gameDeathListener = new ObjectDeathListener() {
|
||||
public void objectDestroyed (ObjectDestroyedEvent event) {
|
||||
unmapTable(event.getTargetOid());
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $Id: TableManagerProvider.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
/**
|
||||
* A place manager that wishes to provide table matchmaking services in
|
||||
* its place needs to create a table manager and make it available by
|
||||
* implementing this interface. The table invocation services and the
|
||||
* table manager will take care of the rest.
|
||||
*/
|
||||
public interface TableManagerProvider
|
||||
{
|
||||
/**
|
||||
* Returns a reference to the table manager that is responsible for
|
||||
* table management in this lobby.
|
||||
*/
|
||||
public TableManager getTableManager ();
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
//
|
||||
// $Id$
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2005 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.awt.Color;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.Icon;
|
||||
|
||||
import com.samskivert.swing.GroupLayout;
|
||||
import com.samskivert.swing.VGroupLayout;
|
||||
import com.samskivert.swing.util.SwingUtil;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.crowd.client.PlaceView;
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.parlor.game.data.GameObject;
|
||||
import com.threerings.parlor.turn.data.TurnGameObject;
|
||||
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
import com.threerings.presents.dobj.AttributeChangedEvent;
|
||||
import com.threerings.presents.dobj.ElementUpdateListener;
|
||||
import com.threerings.presents.dobj.ElementUpdatedEvent;
|
||||
import com.threerings.presents.dobj.DObject;
|
||||
|
||||
/**
|
||||
* Automatically display a list of players and turn change information
|
||||
* in a turn-based game.
|
||||
*/
|
||||
// TODO
|
||||
// - adapt this to be able to display scores in some generic way as well.
|
||||
// - allow configuring of turn / winner labels from prototypes,
|
||||
// rather than forcing one to be an icon, the other a string, and
|
||||
// examine the prototype to determine how to highlight the turnholder.
|
||||
public class TurnDisplay extends JPanel
|
||||
implements PlaceView, AttributeChangeListener, ElementUpdateListener
|
||||
{
|
||||
/**
|
||||
* Create a TurnDisplay.
|
||||
*/
|
||||
public TurnDisplay ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TurnDisplay for a game using the specified Icon to denote
|
||||
* whose turn it is.
|
||||
*/
|
||||
public TurnDisplay (Icon turnIcon)
|
||||
{
|
||||
setTurnIcon(turnIcon);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the icon to use.
|
||||
*/
|
||||
public void setTurnIcon (Icon turnIcon)
|
||||
{
|
||||
_turnIcon = turnIcon;
|
||||
if (_turnObj != null) {
|
||||
createList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the text to be displayed next to the winner's name.
|
||||
*/
|
||||
public void setWinnerText (String winnerText)
|
||||
{
|
||||
_winnerText = winnerText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set optional icons to use for identifying each player in the game.
|
||||
*/
|
||||
public void setPlayerIcons (Icon[] icons)
|
||||
{
|
||||
_playerIcons = icons;
|
||||
if (_turnObj != null) {
|
||||
createList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the list of names and highlight as appropriate.
|
||||
*/
|
||||
protected void createList ()
|
||||
{
|
||||
removeAll();
|
||||
_labels.clear();
|
||||
|
||||
GridBagLayout gridbag = new GridBagLayout();
|
||||
setLayout(gridbag);
|
||||
|
||||
GridBagConstraints iconC = new GridBagConstraints();
|
||||
GridBagConstraints labelC = new GridBagConstraints();
|
||||
iconC.fill = labelC.fill = GridBagConstraints.BOTH;
|
||||
labelC.weightx = 1.0;
|
||||
labelC.insets.left = 10;
|
||||
labelC.gridwidth = GridBagConstraints.REMAINDER;
|
||||
|
||||
Name[] names = _turnObj.getPlayers();
|
||||
boolean[] winners = ((GameObject) _turnObj).winners;
|
||||
Name holder = _turnObj.getTurnHolder();
|
||||
for (int ii=0, jj=0; ii < names.length; ii++, jj++) {
|
||||
if (names[ii] == null) continue;
|
||||
|
||||
JLabel iconLabel = new JLabel();
|
||||
if (winners == null) {
|
||||
if (names[ii].equals(holder)) {
|
||||
iconLabel.setIcon(_turnIcon);
|
||||
}
|
||||
} else if (winners[ii]) {
|
||||
iconLabel.setText(_winnerText);
|
||||
iconLabel.setForeground(Color.GREEN);
|
||||
}
|
||||
_labels.put(names[ii], iconLabel);
|
||||
add(iconLabel, iconC);
|
||||
|
||||
JLabel label = new JLabel(names[ii].toString());
|
||||
if (_playerIcons != null) {
|
||||
label.setIcon(_playerIcons[jj]);
|
||||
}
|
||||
add(label, labelC);
|
||||
}
|
||||
|
||||
SwingUtil.refresh(this);
|
||||
}
|
||||
|
||||
// documentation inherited from interface PlaceView
|
||||
public void willEnterPlace (PlaceObject plobj)
|
||||
{
|
||||
_turnObj = (TurnGameObject) plobj;
|
||||
plobj.addListener(this);
|
||||
createList();
|
||||
}
|
||||
|
||||
// documentation inherited from interface PlaceView
|
||||
public void didLeavePlace (PlaceObject plobj)
|
||||
{
|
||||
plobj.removeListener(this);
|
||||
_turnObj = null;
|
||||
removeAll();
|
||||
}
|
||||
|
||||
// documentation inherited from interface AttributeChangeListener
|
||||
public void attributeChanged (AttributeChangedEvent event)
|
||||
{
|
||||
String name = event.getName();
|
||||
if (name.equals(_turnObj.getTurnHolderFieldName())) {
|
||||
JLabel oldLabel = (JLabel) _labels.get((Name) event.getOldValue());
|
||||
if (oldLabel != null) {
|
||||
oldLabel.setIcon(null);
|
||||
}
|
||||
JLabel newLabel = (JLabel) _labels.get((Name) event.getValue());
|
||||
if (newLabel != null) {
|
||||
newLabel.setIcon(_turnIcon);
|
||||
}
|
||||
|
||||
} else if (name.equals(GameObject.PLAYERS)) {
|
||||
createList();
|
||||
|
||||
} else if (name.equals(GameObject.WINNERS)) {
|
||||
createList();
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited from interface ElementUpdateListener
|
||||
public void elementUpdated (ElementUpdatedEvent event)
|
||||
{
|
||||
String name = event.getName();
|
||||
if (name.equals(GameObject.PLAYERS)) {
|
||||
createList();
|
||||
}
|
||||
}
|
||||
|
||||
/** The TurnGameObject we're displaying. */
|
||||
protected TurnGameObject _turnObj;
|
||||
|
||||
/** A mapping of the labels currently associated with each player. */
|
||||
protected HashMap _labels = new HashMap();
|
||||
|
||||
/** The game-specified player icons. */
|
||||
protected Icon[] _playerIcons;
|
||||
|
||||
/** The text to display next to a winner's name. */
|
||||
protected String _winnerText;
|
||||
|
||||
/** The Icon we use for indicating the turn. */
|
||||
protected Icon _turnIcon;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// $Id: TurnGameController.java 3381 2005-03-03 19:36:34Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.parlor.game.client.GameController;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void turnDidChange (Name turnHolder);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
//
|
||||
// $Id: TurnGameControllerDelegate.java 3758 2005-11-10 23:18:58Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.AttributeChangedEvent;
|
||||
import com.threerings.presents.dobj.AttributeChangeListener;
|
||||
|
||||
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
|
||||
{
|
||||
/**
|
||||
* Constructs a delegate which will call back to the supplied {@link
|
||||
* TurnGameController} implementation wen turn-based game related
|
||||
* things happen.
|
||||
*/
|
||||
public TurnGameControllerDelegate (TurnGameController tgctrl)
|
||||
{
|
||||
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 boolean isOurTurn ()
|
||||
{
|
||||
BodyObject self = (BodyObject)_ctx.getClient().getClientObject();
|
||||
return (_gameObj.state == GameObject.IN_PLAY &&
|
||||
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 int getTurnHolderIndex ()
|
||||
{
|
||||
return _gameObj.getPlayerIndex(_turnGame.getTurnHolder());
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void init (CrowdContext ctx, PlaceConfig config)
|
||||
{
|
||||
_ctx = ctx;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void willEnterPlace (PlaceObject plobj)
|
||||
{
|
||||
// get a casted reference to the object
|
||||
_gameObj = (GameObject)plobj;
|
||||
_turnGame = (TurnGameObject)plobj;
|
||||
_thfield = _turnGame.getTurnHolderFieldName();
|
||||
|
||||
// and add ourselves as a listener
|
||||
plobj.addListener(this);
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void didLeavePlace (PlaceObject plobj)
|
||||
{
|
||||
// remove our listenership
|
||||
plobj.removeListener(this);
|
||||
|
||||
// clean up
|
||||
_turnGame = null;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void attributeChanged (AttributeChangedEvent event)
|
||||
{
|
||||
// handle turn changes
|
||||
if (event.getName().equals(_thfield)) {
|
||||
Name name = (Name)event.getValue();
|
||||
Name oname = (Name)event.getOldValue();
|
||||
if (TurnGameObject.TURN_HOLDER_REPLACED.equals(name) ||
|
||||
TurnGameObject.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 TurnGameController _tgctrl;
|
||||
|
||||
/** A reference to our client context. */
|
||||
protected CrowdContext _ctx;
|
||||
|
||||
/** A reference to our game object. */
|
||||
protected GameObject _gameObj;
|
||||
|
||||
/** A casted reference to our game object as a turn game. */
|
||||
protected TurnGameObject _turnGame;
|
||||
|
||||
/** The name of the turn holder field. */
|
||||
protected String _thfield;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// $Id: TurnGameObject.java 3667 2005-08-03 07:46:54Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.util.Name;
|
||||
|
||||
import com.threerings.parlor.game.data.GameObject;
|
||||
|
||||
/**
|
||||
* Games that wish to support turn-based play must implement this
|
||||
* interface with their {@link GameObject}.
|
||||
*/
|
||||
public interface TurnGameObject
|
||||
{
|
||||
/** 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 final Name TURN_HOLDER_REPLACED =
|
||||
new Name("__TURN_HOLDER_REPLACED__");
|
||||
|
||||
/**
|
||||
* Returns the distributed object field name of the
|
||||
* <code>turnHolder</code> field in the object that implements this
|
||||
* interface.
|
||||
*/
|
||||
public String getTurnHolderFieldName ();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public Name getTurnHolder ();
|
||||
|
||||
/**
|
||||
* Requests that the <code>turnHolder</code> field be set to the specified
|
||||
* value.
|
||||
*/
|
||||
public void setTurnHolder (Name turnHolder);
|
||||
|
||||
/**
|
||||
* Returns the array of player names involved in the game.
|
||||
*/
|
||||
public Name[] getPlayers ();
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// $Id: TurnGameManager.java 3390 2005-03-10 00:13:25Z tedv $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
|
||||
/**
|
||||
* A game manager that wishes to make use of the turn game services should
|
||||
* implement this interface and create a {@link TurnGameManagerDelegate}
|
||||
* which will perform the basic turn game processing and call back to the
|
||||
* main manager via this interface.
|
||||
*
|
||||
* <p> The basic flow of a turn-based game is as follows:
|
||||
* <pre>
|
||||
* GameManager.gameWillStart()
|
||||
* GameManager.gameDidStart()
|
||||
* TurnGameManagerDelegate.setFirstTurnHolder()
|
||||
* TurnGameManagerDelegate.startTurn()
|
||||
* TurnGameManager.turnWillStart()
|
||||
* TurnGameManagerDelegate.endTurn()
|
||||
* TurnGameManager.turnDidEnd()
|
||||
* TurnGameManagerDelegate.setNextTurnHolder()
|
||||
* TurnGameManagerDelegate.startTurn()
|
||||
* ...
|
||||
* GameManager.endGame()
|
||||
* </pre>
|
||||
*/
|
||||
public interface TurnGameManager
|
||||
{
|
||||
/**
|
||||
* Extending {@link GameManager} should automatically handle
|
||||
* implementing this method.
|
||||
*/
|
||||
public Name getPlayerName (int index);
|
||||
|
||||
/**
|
||||
* Extending {@link GameManager} should automatically handle
|
||||
* implementing this method.
|
||||
*/
|
||||
public int getPlayerIndex (Name username);
|
||||
|
||||
/**
|
||||
* Extending {@link GameManager} should automatically handle
|
||||
* implementing this method.
|
||||
*/
|
||||
public int getPlayerCount ();
|
||||
|
||||
/**
|
||||
* Extending {@link GameManager} should automatically handle
|
||||
* implementing this method.
|
||||
*/
|
||||
public boolean isActivePlayer (int pidx);
|
||||
|
||||
/**
|
||||
* Called when we are about to start the next turn. Implementations
|
||||
* can do whatever pre-start turn activities need to be done.
|
||||
*/
|
||||
public void turnWillStart ();
|
||||
|
||||
/**
|
||||
* Called when we have started the next turn. Implementations can do
|
||||
* whatever post-start turn activities need to be done.
|
||||
*/
|
||||
public void turnDidStart ();
|
||||
|
||||
/**
|
||||
* Called when the turn was ended. Implementations can perform any
|
||||
* post-turn processing (like updating scores, etc.).
|
||||
*/
|
||||
public void turnDidEnd ();
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
//
|
||||
// $Id: TurnGameManagerDelegate.java 4188 2006-06-13 18:03:48Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.server;
|
||||
|
||||
import com.samskivert.util.RandomUtil;
|
||||
import com.threerings.util.Name;
|
||||
|
||||
import com.threerings.crowd.data.PlaceObject;
|
||||
|
||||
import com.threerings.parlor.Log;
|
||||
import com.threerings.parlor.game.server.GameManager;
|
||||
import com.threerings.parlor.game.server.GameManagerDelegate;
|
||||
|
||||
import com.threerings.parlor.turn.data.TurnGameObject;
|
||||
|
||||
/**
|
||||
* Performs the server-side turn-based game processing for a turn based
|
||||
* game. Game managers which wish to make use of the turn services must
|
||||
* implement {@link TurnGameManager} and either create an instance of this
|
||||
* class, or an instance of a derivation which customizes the behavior,
|
||||
* either of which would be passed to {@link GameManager#addDelegate} to
|
||||
* be activated.
|
||||
*/
|
||||
public class TurnGameManagerDelegate extends GameManagerDelegate
|
||||
{
|
||||
/**
|
||||
* Constructs a delegate that will manage the turn game state and call
|
||||
* back to the supplied {@link TurnGameManager} implementation to let
|
||||
* it in on the progression of the game.
|
||||
*/
|
||||
public TurnGameManagerDelegate (TurnGameManager tgmgr)
|
||||
{
|
||||
super((GameManager)tgmgr);
|
||||
_tgmgr = tgmgr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <code>-1</code> if there is no current turn holder.
|
||||
*/
|
||||
public int getTurnHolderIndex ()
|
||||
{
|
||||
return _tgmgr.getPlayerIndex(_turnGame.getTurnHolder());
|
||||
}
|
||||
|
||||
/** Test if it's the inputted player's turn. */
|
||||
public boolean isPlayersTurn (int playerIndex)
|
||||
{
|
||||
// Don't accidently match a visitor's id of -1 with the "no one's
|
||||
// turn" state of turn -1.
|
||||
int turnHolder = getTurnHolderIndex();
|
||||
if (turnHolder < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's this player's turn if the ids match
|
||||
return (turnHolder == playerIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to start the next turn. It calls {@link
|
||||
* TurnGameManager#turnWillStart} to allow our owning manager to
|
||||
* perform any pre-start turn processing, sets the turn holder that
|
||||
* was configured either when the game started or when finishing up
|
||||
* the last turn, and then calls {@link TurnGameManager#turnDidStart}
|
||||
* to allow the manager to perform any post-start turn
|
||||
* processing. This assumes that a valid turn holder has been
|
||||
* assigned. If some pre-game preparation needs to take place in a
|
||||
* non-turn-based manner, this function should not be called until it
|
||||
* is time to start the first turn.
|
||||
*/
|
||||
public void startTurn ()
|
||||
{
|
||||
// sanity check
|
||||
if (_turnIdx < 0 || _turnIdx >= _turnGame.getPlayers().length) {
|
||||
Log.warning("startTurn() called with invalid turn index " +
|
||||
"[game=" + where() + ", turnIdx=" + _turnIdx + "].");
|
||||
// abort, abort
|
||||
return;
|
||||
}
|
||||
|
||||
// get the player name and sanity-check again
|
||||
Name name = _tgmgr.getPlayerName(_turnIdx);
|
||||
if (name == null) {
|
||||
Log.warning("startTurn() called with invalid player " +
|
||||
"[game=" + where() + ", turnIdx=" + _turnIdx + "].");
|
||||
return;
|
||||
}
|
||||
|
||||
// do pre-start processing
|
||||
_tgmgr.turnWillStart();
|
||||
|
||||
// and set the turn indicator accordingly
|
||||
_turnGame.setTurnHolder(name);
|
||||
|
||||
// do post-start processing
|
||||
_tgmgr.turnDidStart();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to end the turn. Whatever indication a game manager has that
|
||||
* the turn has ended (probably the submission of a valid move of some
|
||||
* sort by the turn holding player), it should call this function to
|
||||
* cause this turn to end and the next to begin.
|
||||
*
|
||||
* <p> If the next turn should not be started immediately after this
|
||||
* turn, the game manager should arrange for {@link
|
||||
* #setNextTurnHolder} to set the {@link #_turnIdx} field to
|
||||
* <code>-1</code> which will cause us not to start the next turn. It
|
||||
* can then call {@link GameManager#endGame} if the game is over or do
|
||||
* whatever else it needs to do outside the context of the turn flow.
|
||||
* To start things back up again it would set {@link #_turnIdx} to the
|
||||
* next turn holder and call {@link #startTurn} itself.
|
||||
*/
|
||||
public void endTurn ()
|
||||
{
|
||||
// let the manager know that the turn is over
|
||||
_tgmgr.turnDidEnd();
|
||||
|
||||
// figure out who's up next
|
||||
setNextTurnHolder();
|
||||
|
||||
// and start the next turn if desired
|
||||
if (_turnIdx != -1) {
|
||||
startTurn();
|
||||
|
||||
} else {
|
||||
// otherwise, clear out the turn holder
|
||||
_turnGame.setTurnHolder(null);
|
||||
}
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void didStartup (PlaceObject plobj)
|
||||
{
|
||||
_turnGame = (TurnGameObject)plobj;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void playerWasReplaced (int pidx, Name oplayer, Name nplayer)
|
||||
{
|
||||
// we need to update the turn holder if the current turn holder
|
||||
// was the player that was replaced and we need to do so in a way
|
||||
// that doesn't make everyone think that the turn just changed
|
||||
if (oplayer != null && oplayer.equals(_turnGame.getTurnHolder())) {
|
||||
// small hackery: this will indicate to the client that we are
|
||||
// replacing the turn holder rather than changing the turn
|
||||
_turnGame.setTurnHolder(TurnGameObject.TURN_HOLDER_REPLACED);
|
||||
_turnGame.setTurnHolder(nplayer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be called from {@link GameManager#gameDidStart} to let
|
||||
* the turn delegate perform start of game processing.
|
||||
*/
|
||||
public void gameDidStart ()
|
||||
{
|
||||
// figure out who will be first
|
||||
setFirstTurnHolder();
|
||||
|
||||
// and start the first turn if we should apparently do so
|
||||
if (_turnIdx != -1) {
|
||||
startTurn();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to determine which player will take the first
|
||||
* turn. The default implementation chooses a player at random.
|
||||
*/
|
||||
protected void setFirstTurnHolder ()
|
||||
{
|
||||
int size = _turnGame.getPlayers().length;
|
||||
int firstPick = _turnIdx = RandomUtil.getInt(size);
|
||||
while (!_tgmgr.isActivePlayer(_turnIdx)) {
|
||||
_turnIdx = (_turnIdx + 1) % size;
|
||||
if (_turnIdx == firstPick) {
|
||||
Log.warning("No players eligible for first turn. Choking. " +
|
||||
"[game=" + where() + "].");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called to determine which player will next hold the turn.
|
||||
* The default implementation simply rotates through the players in
|
||||
* order, but some games may need to mess with the turn from time to
|
||||
* time. This should update the <code>_turnIdx</code> field, not set
|
||||
* the turn holder field in the game object directly.
|
||||
*/
|
||||
protected void setNextTurnHolder ()
|
||||
{
|
||||
// stick with the current player if they're the only participant
|
||||
if (_tgmgr.getPlayerCount() == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// find the next occupied active player slot
|
||||
int size = _turnGame.getPlayers().length;
|
||||
int oturnIdx = _turnIdx;
|
||||
do {
|
||||
_turnIdx = (_turnIdx + 1) % size;
|
||||
if (_turnIdx == oturnIdx) {
|
||||
// if we've wrapped all the way around, stop where we are
|
||||
// even if the current player is not active.
|
||||
Log.warning("1 or less active players. Unable to properly " +
|
||||
"change turn. [game=" + where() + "].");
|
||||
break;
|
||||
}
|
||||
} while (!_tgmgr.isActivePlayer(_turnIdx));
|
||||
}
|
||||
|
||||
/** The game manager for which we are delegating. */
|
||||
protected TurnGameManager _tgmgr;
|
||||
|
||||
/** A reference to our game object. */
|
||||
protected TurnGameObject _turnGame;
|
||||
|
||||
/** The player index of the current turn holder or <code>-1</code> if
|
||||
* it's no one's turn. */
|
||||
protected int _turnIdx = -1;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// $Id: ParlorContext.java 4191 2006-06-13 22:42:20Z ray $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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.
|
||||
*/
|
||||
public ParlorDirector getParlorDirector ();
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// $Id: RobotPlayer.java 4188 2006-06-13 18:03:48Z mdb $
|
||||
//
|
||||
// Narya library - tools for developing networked games
|
||||
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
|
||||
// http://www.threerings.net/code/narya/
|
||||
//
|
||||
// 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 java.awt.Component;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.samskivert.swing.Controller;
|
||||
import com.samskivert.util.CollectionUtil;
|
||||
import com.samskivert.util.Interval;
|
||||
import com.samskivert.util.RandomUtil;
|
||||
|
||||
import com.threerings.util.KeyTranslator;
|
||||
|
||||
/**
|
||||
* The robot player is a computer player with truly rudimentary artificial
|
||||
* intelligence that periodically posts random commands selected from the
|
||||
* available key press and release commands to the target component.
|
||||
*
|
||||
* Note that {@link java.awt.Robot} could have been used to post key
|
||||
* events to the target component rather than commands, but not all key
|
||||
* events can be simulated in that fashion (e.g., a right shift key
|
||||
* press), and this seemed somehow more proper in any case.
|
||||
*/
|
||||
public class RobotPlayer extends Interval
|
||||
{
|
||||
/**
|
||||
* Constructs a robot player.
|
||||
*/
|
||||
public RobotPlayer (Component target, KeyTranslator xlate)
|
||||
{
|
||||
// save off references
|
||||
_target = target;
|
||||
_xlate = xlate;
|
||||
|
||||
// build the list of available commands
|
||||
CollectionUtil.addAll(_press, _xlate.enumeratePressCommands());
|
||||
CollectionUtil.addAll(_release, _xlate.enumerateReleaseCommands());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the robot player is actively posting action commands.
|
||||
*/
|
||||
public void setActive (boolean active)
|
||||
{
|
||||
if (active != _active) {
|
||||
if (active) {
|
||||
schedule(_robotDelay, true);
|
||||
} else {
|
||||
cancel(); // stop the robot player
|
||||
}
|
||||
_active = active;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the delay in milliseconds between posting each action command.
|
||||
*/
|
||||
public void setRobotDelay (long delay)
|
||||
{
|
||||
_robotDelay = delay;
|
||||
|
||||
// if the robot is active, reset it with the new delay time
|
||||
if (isActive()) {
|
||||
setActive(false);
|
||||
setActive(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the robot is currently active and periodically
|
||||
* posting action commands.
|
||||
*/
|
||||
public boolean isActive ()
|
||||
{
|
||||
return _active;
|
||||
}
|
||||
|
||||
// documentation inherited
|
||||
public void expired ()
|
||||
{
|
||||
// post a random key press command
|
||||
int idx = RandomUtil.getInt(_press.size());
|
||||
String command = (String)_press.get(idx);
|
||||
// Log.info("Posting artificial command [cmd=" + command + "].");
|
||||
Controller.postAction(_target, command);
|
||||
}
|
||||
|
||||
/** The default robot delay. */
|
||||
protected static final long DEFAULT_ROBOT_DELAY = 500L;
|
||||
|
||||
/** Whether the robot is active or not. */
|
||||
protected boolean _active = false;
|
||||
|
||||
/** The milliseconds between posting each action command. */
|
||||
protected long _robotDelay = DEFAULT_ROBOT_DELAY;
|
||||
|
||||
/** The list of available key press action commands. */
|
||||
protected ArrayList _press = new ArrayList();
|
||||
|
||||
/** The list of available key release action commands. */
|
||||
protected ArrayList _release = new ArrayList();
|
||||
|
||||
/** The key translator that describes available keys and commands. */
|
||||
protected KeyTranslator _xlate;
|
||||
|
||||
/** The target component associated with game action commands. */
|
||||
protected Component _target;
|
||||
}
|
||||
Reference in New Issue
Block a user