From 738cf657cbd0dd3e1cf9f260ced29a10661dc4fa Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Wed, 3 Aug 2005 07:46:54 +0000 Subject: [PATCH] Allow a player to be replaced in an in-play game; properly handle the case in a turn-based game where the turn holder is replaced and update the turnHolder field in a way that doesn't cause the client to think that the turn changed. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3667 542714f4-19e9-0310-aa3c-eee0fc999fb1 --- .../parlor/game/server/GameManager.java | 30 +++++++++++++++++++ .../game/server/GameManagerDelegate.java | 10 +++++++ .../client/TurnGameControllerDelegate.java | 13 +++++++- .../parlor/turn/data/TurnGameObject.java | 6 ++++ .../turn/server/TurnGameManagerDelegate.java | 14 +++++++++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/java/com/threerings/parlor/game/server/GameManager.java b/src/java/com/threerings/parlor/game/server/GameManager.java index 6cab1fe9d..a508adf62 100644 --- a/src/java/com/threerings/parlor/game/server/GameManager.java +++ b/src/java/com/threerings/parlor/game/server/GameManager.java @@ -270,6 +270,36 @@ public class GameManager extends PlaceManager { } + /** + * Replaces the player at the specified index and calls {@link + * #playerWasReplaced} to let derived classes and delegates know + * what's going on. + */ + public void replacePlayer (final int pidx, final Name player) + { + final Name oplayer = _gameobj.players[pidx]; + _gameobj.setPlayersAt(player, pidx); + + // allow derived classes to respond + playerWasReplaced(pidx, oplayer, player); + + // notify our delegates + applyToDelegates(new DelegateOp() { + public void apply (PlaceManagerDelegate delegate) { + ((GameManagerDelegate)delegate).playerWasReplaced( + pidx, oplayer, player); + } + }); + } + + /** + * Called when a player has been replaced via a call to {@link + * #replacePlayer}. + */ + protected void playerWasReplaced (int pidx, Name oldPlayer, Name newPlayer) + { + } + /** * Returns the user object for the player with the specified index or * null if the player at that index is not online. diff --git a/src/java/com/threerings/parlor/game/server/GameManagerDelegate.java b/src/java/com/threerings/parlor/game/server/GameManagerDelegate.java index 03485ed47..85fe16433 100644 --- a/src/java/com/threerings/parlor/game/server/GameManagerDelegate.java +++ b/src/java/com/threerings/parlor/game/server/GameManagerDelegate.java @@ -21,6 +21,8 @@ package com.threerings.parlor.game.server; +import com.threerings.util.Name; + import com.threerings.crowd.server.PlaceManagerDelegate; import com.threerings.parlor.game.data.GameAI; @@ -54,6 +56,14 @@ public class GameManagerDelegate extends PlaceManagerDelegate { } + /** + * 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. diff --git a/src/java/com/threerings/parlor/turn/client/TurnGameControllerDelegate.java b/src/java/com/threerings/parlor/turn/client/TurnGameControllerDelegate.java index 4f8f649fd..f5b7fcac5 100644 --- a/src/java/com/threerings/parlor/turn/client/TurnGameControllerDelegate.java +++ b/src/java/com/threerings/parlor/turn/client/TurnGameControllerDelegate.java @@ -117,7 +117,18 @@ public class TurnGameControllerDelegate extends GameControllerDelegate { // handle turn changes if (event.getName().equals(_thfield)) { - _tgctrl.turnDidChange((Name)event.getValue()); + 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); + } } } diff --git a/src/java/com/threerings/parlor/turn/data/TurnGameObject.java b/src/java/com/threerings/parlor/turn/data/TurnGameObject.java index 3a7c53f91..fdd640471 100644 --- a/src/java/com/threerings/parlor/turn/data/TurnGameObject.java +++ b/src/java/com/threerings/parlor/turn/data/TurnGameObject.java @@ -31,6 +31,12 @@ import com.threerings.parlor.game.data.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 * turnHolder field in the object that implements this diff --git a/src/java/com/threerings/parlor/turn/server/TurnGameManagerDelegate.java b/src/java/com/threerings/parlor/turn/server/TurnGameManagerDelegate.java index 284c65c09..b3d31d7da 100644 --- a/src/java/com/threerings/parlor/turn/server/TurnGameManagerDelegate.java +++ b/src/java/com/threerings/parlor/turn/server/TurnGameManagerDelegate.java @@ -158,6 +158,20 @@ public class TurnGameManagerDelegate extends GameManagerDelegate _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.