From 0c3eb9a28363ae697f984d9413eb187bfe2511a9 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Mon, 20 Jun 2011 06:41:15 +0200 Subject: Fixed a bunch of network synchronization bugs git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@510 72836036-5685-4462-b002-a69064685172 --- src/jrummikub/control/RoundControl.java | 81 ++++++++++++---------- .../control/network/ConnectionControl.java | 23 ++++-- .../control/network/IConnectionControl.java | 6 +- .../control/network/NetworkRoundControl.java | 18 ++--- .../control/network/NetworkTurnControl.java | 44 ++++++------ src/jrummikub/control/turn/AIControl.java | 2 +- .../control/turn/AbstractTurnControl.java | 7 +- src/jrummikub/control/turn/HumanTurnControl.java | 2 +- src/jrummikub/control/turn/ITurnControl.java | 3 +- 9 files changed, 110 insertions(+), 76 deletions(-) (limited to 'src/jrummikub') diff --git a/src/jrummikub/control/RoundControl.java b/src/jrummikub/control/RoundControl.java index ba0fa2a..63ec1a2 100644 --- a/src/jrummikub/control/RoundControl.java +++ b/src/jrummikub/control/RoundControl.java @@ -18,7 +18,7 @@ import jrummikub.model.IHand; import jrummikub.model.IPlayer; import jrummikub.model.IRoundState; import jrummikub.model.ITable; -import jrummikub.model.PlayerSettings; +import jrummikub.model.PlayerSettings.Type; import jrummikub.model.Position; import jrummikub.model.Score; import jrummikub.model.Stone; @@ -29,7 +29,7 @@ import jrummikub.util.Event1; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IListener; -import jrummikub.util.IListener1; +import jrummikub.util.IListener3; import jrummikub.util.Pair; import jrummikub.view.IView; import jrummikub.view.IView.BottomPanelType; @@ -153,14 +153,11 @@ public class RoundControl { .getType() == HUMAN; boolean oneHuman = roundState.getGameSettings().oneHuman(); - clonedTable = (ITable) roundState.getTable().clone(); - clonedHand = (IHand) roundState.getActivePlayer().getHand().clone(); - if (isHuman && !oneHuman) { view.setBottomPanel(BottomPanelType.START_TURN_PANEL); } - view.getTablePanel().setStoneSets(clonedTable.clone()); + view.getTablePanel().setStoneSets(roundState.getTable().clone()); view.setCurrentPlayerName(roundState.getActivePlayer().getPlayerSettings() .getName()); view.setCurrentPlayerColor(roundState.getActivePlayer().getPlayerSettings() @@ -168,7 +165,7 @@ public class RoundControl { view.setCurrentPlayerHasLaidOut(roundState.getActivePlayer().getLaidOut()); turnControl = createTurnControl(roundState.getActivePlayer() - .getPlayerSettings()); + .getPlayerSettings().getType()); } protected void startTurn() { @@ -184,6 +181,11 @@ public class RoundControl { TurnMode turnMode = TurnMode.NORMAL_TURN; + view.getTablePanel().setStoneSets(roundState.getTable().clone()); + + clonedTable = (ITable) roundState.getTable().clone(); + clonedHand = (IHand) roundState.getActivePlayer().getHand().clone(); + if (roundState.getTurnNumber() < 1) { view.setStoneCollectionHidden(true); turnMode = TurnMode.INSPECT_ONLY; @@ -199,12 +201,20 @@ public class RoundControl { turnControl.setup(new ITurnControl.TurnInfo(clonedTable, clonedHand, roundState.getActivePlayer().getLaidOut(), turnMode), roundState .getGameSettings(), view); - turnControl.getEndOfTurnEvent().add(new IListener1() { - @Override - public void handle(ITable newTable) { - endOfTurn(newTable); - } - }); + turnControl.getEndOfTurnEvent().add( + new IListener3() { + @Override + public void handle(IHand oldHand, ITable oldTable, ITable newTable) { + if (oldHand == null) { + oldHand = roundState.getActivePlayer().getHand(); + } + if (oldTable == null) { + oldTable = roundState.getTable(); + } + + endOfTurn(oldHand, oldTable, newTable); + } + }); turnControl.getRedealEvent().add(new IListener() { @Override public void handle() { @@ -233,8 +243,8 @@ public class RoundControl { protected void addTurnControlListeners(ITurnControl turnControl) { } - protected ITurnControl createTurnControl(PlayerSettings playerSettings) { - return TurnControlFactory.getFactory(playerSettings.getType()).create(); + protected ITurnControl createTurnControl(Type type) { + return TurnControlFactory.getFactory(type).create(); } void deal() { @@ -248,9 +258,8 @@ public class RoundControl { view.getSidePanel().setHeapSize(roundState.getGameHeap().getSize()); } - private boolean laidOutValidPoints() { - List newSets = tableSetDifference(roundState.getTable(), - clonedTable); + private boolean laidOutValidPoints(ITable oldTable, ITable newTable) { + List newSets = tableSetDifference(oldTable, newTable); int totalValue = 0; for (StoneSet set : newSets) { @@ -261,10 +270,12 @@ public class RoundControl { || totalValue >= roundState.getGameSettings().getInitialMeldThreshold(); } - protected void endOfTurn(ITable newTable) { + protected void endOfTurn(IHand oldHand, ITable oldTable, ITable newTable) { boolean wasHuman = (turnControl instanceof HumanTurnControl); boolean wasAI = (turnControl instanceof AIControl); + view.setBottomPanel(BottomPanelType.NONHUMAN_HAND_PANEL); + turnControl = null; roundState.getActivePlayer().setLastTurnInvalid(false); @@ -278,7 +289,7 @@ public class RoundControl { lastTurnNotEnoughPoints = false; lastTurnMeldError = false; if (roundState.getTurnNumber() >= 1) { - goToNextPlayer = checkTurn(newTable); + goToNextPlayer = checkTurn(oldTable, newTable); } if (goToNextPlayer || wasAI) { nextPlayer(); @@ -290,11 +301,10 @@ public class RoundControl { if (lastTurnNotEnoughPoints) { view.setInitialMeldError(roundState.getGameSettings() .getInitialMeldThreshold()); - view.setInvalidStoneSets(tableSetDifference(roundState.getTable(), - newTable)); + view.setInvalidStoneSets(tableSetDifference(oldTable, newTable)); } else if (lastTurnMeldError) { view.setInitialMeldFirstError(); - view.setInvalidStoneSets(touchedStoneSets(newTable)); + view.setInvalidStoneSets(touchedStoneSets(oldHand, oldTable, newTable)); } else { view.setStoneCollectionHidden(true); view.setInvalidStoneSets(invalidStoneSets(newTable)); @@ -313,11 +323,12 @@ public class RoundControl { return invalidSets; } - private List touchedStoneSets(ITable newTable) { + private List touchedStoneSets(IHand oldHand, ITable oldTable, + ITable newTable) { List touchedSets = new ArrayList(); - for (StoneSet set : tableSetDifference(roundState.getTable(), newTable)) { + for (StoneSet set : tableSetDifference(oldTable, newTable)) { for (Stone stone : set) { - if (!roundState.getActivePlayer().getHand().contains(stone)) { + if (!oldHand.contains(stone)) { touchedSets.add(set); break; } @@ -353,25 +364,25 @@ public class RoundControl { } } - private boolean checkTurn(ITable newTable) { + private boolean checkTurn(ITable oldTable, ITable newTable) { if (!newTable.isValid()) { - rejectMove(newTable); + rejectMove(oldTable, newTable); return false; } if (!roundState.getActivePlayer().getLaidOut()) { // Player touched forbidden stones - if (!tableSetDifference(newTable, roundState.getTable()).isEmpty()) { - rejectMove(newTable); + if (!tableSetDifference(newTable, oldTable).isEmpty()) { + rejectMove(oldTable, newTable); lastTurnMeldError = true; return false; } - if (!laidOutValidPoints()) { - rejectMove(newTable); + if (!laidOutValidPoints(oldTable, newTable)) { + rejectMove(oldTable, newTable); lastTurnNotEnoughPoints = true; return false; } } - Set tableDiff = tableDifference(roundState.getTable(), newTable); + Set tableDiff = tableDifference(oldTable, newTable); roundState.setTable(newTable); @@ -387,8 +398,8 @@ public class RoundControl { return true; } - private void rejectMove(ITable newTable) { - Set tableDiff = tableDifference(roundState.getTable(), newTable); + private void rejectMove(ITable oldTable, ITable newTable) { + Set tableDiff = tableDifference(oldTable, newTable); // deal penalty, reset roundState.getGameHeap().putBack(tableDiff); roundState.getActivePlayer().setLastTurnInvalid(true); diff --git a/src/jrummikub/control/network/ConnectionControl.java b/src/jrummikub/control/network/ConnectionControl.java index d791344..871d06b 100644 --- a/src/jrummikub/control/network/ConnectionControl.java +++ b/src/jrummikub/control/network/ConnectionControl.java @@ -6,15 +6,18 @@ import java.util.UUID; import javax.swing.SwingUtilities; import jrummikub.model.GameSettings; +import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.Event; import jrummikub.util.Event1; import jrummikub.util.Event2; +import jrummikub.util.Event3; import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IEvent2; +import jrummikub.util.IEvent3; import jrummikub.util.LoginData; import jrummikub.view.LoginError; @@ -63,7 +66,7 @@ public class ConnectionControl implements IConnectionControl { private Event roundStartEvent = new Event(); private Event1 tableUpdateEvent = new Event1(); - private Event1 turnEndEvent = new Event1(); + private Event3 turnEndEvent = new Event3(); private Event1 turnStartEvent = new Event1(); private GameData currentGame; @@ -163,7 +166,7 @@ public class ConnectionControl implements IConnectionControl { } @Override - public IEvent1 getTurnEndEvent() { + public IEvent3 getTurnEndEvent() { return turnEndEvent; } @@ -302,14 +305,20 @@ public class ConnectionControl implements IConnectionControl { } @Override - public void endTurn(final ITable table) { + public void endTurn(final IHand oldHand, final ITable oldTable, + final ITable newTable) { final UUID uuid = currentGame.getGameID(); run(new SendRunner() { @Override protected void addData(DefaultPacketExtension extension) { extension.setValue("messageType", "turn_end"); extension.setValue("uuid", uuid.toString()); - extension.setValue("table", Base64.encodeObject(table, Base64.GZIP)); + extension.setValue("old_hand", + Base64.encodeObject(oldHand, Base64.GZIP)); + extension.setValue("old_table", + Base64.encodeObject(oldTable, Base64.GZIP)); + extension.setValue("new_table", + Base64.encodeObject(newTable, Base64.GZIP)); } }); } @@ -438,8 +447,10 @@ public class ConnectionControl implements IConnectionControl { tableUpdateEvent.emit((ITable) Base64.decodeToObject(extension .getValue("table"))); } else if (messageType.equals("turn_end")) { - turnEndEvent.emit((ITable) Base64.decodeToObject(extension - .getValue("table"))); + turnEndEvent.emit( + (IHand) Base64.decodeToObject(extension.getValue("old_hand")), + (ITable) Base64.decodeToObject(extension.getValue("old_table")), + (ITable) Base64.decodeToObject(extension.getValue("new_table"))); } else if (messageType.equals("turn_start")) { turnStartEvent.emit((IRoundState) Base64.decodeToObject(extension .getValue("state"))); diff --git a/src/jrummikub/control/network/IConnectionControl.java b/src/jrummikub/control/network/IConnectionControl.java index 52c7fd1..38bc05c 100644 --- a/src/jrummikub/control/network/IConnectionControl.java +++ b/src/jrummikub/control/network/IConnectionControl.java @@ -3,12 +3,14 @@ package jrummikub.control.network; import java.awt.Color; import java.util.UUID; +import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IEvent2; +import jrummikub.util.IEvent3; import jrummikub.view.LoginError; interface IConnectionControl { @@ -41,7 +43,7 @@ interface IConnectionControl { public IEvent1 getTableUpdateEvent(); - public IEvent1 getTurnEndEvent(); + public IEvent3 getTurnEndEvent(); public IEvent1 getTurnStartEvent(); @@ -67,7 +69,7 @@ interface IConnectionControl { public void updateTable(ITable table); - public void endTurn(ITable table); + public void endTurn(IHand oldHand, ITable oldTable, ITable newTable); public void startTurn(IRoundState state); } \ No newline at end of file diff --git a/src/jrummikub/control/network/NetworkRoundControl.java b/src/jrummikub/control/network/NetworkRoundControl.java index a9775b7..81820e7 100644 --- a/src/jrummikub/control/network/NetworkRoundControl.java +++ b/src/jrummikub/control/network/NetworkRoundControl.java @@ -2,9 +2,10 @@ package jrummikub.control.network; import jrummikub.control.RoundControl; import jrummikub.control.turn.ITurnControl; +import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; -import jrummikub.model.PlayerSettings; +import jrummikub.model.PlayerSettings.Type; import jrummikub.util.IListener1; import jrummikub.view.IView; @@ -23,7 +24,8 @@ public class NetworkRoundControl extends RoundControl { new IListener1() { @Override public void handle(IRoundState state) { - NetworkControl.fixGameSettings(state.getGameSettings(), connectionControl.getNickname()); + NetworkControl.fixGameSettings(state.getGameSettings(), + connectionControl.getNickname()); setRoundState(state); startTurn(); @@ -42,8 +44,8 @@ public class NetworkRoundControl extends RoundControl { } @Override - protected ITurnControl createTurnControl(PlayerSettings playerSettings) { - switch (playerSettings.getType()) { + protected ITurnControl createTurnControl(Type type) { + switch (type) { case HUMAN: currentlyActive = true; break; @@ -56,7 +58,7 @@ public class NetworkRoundControl extends RoundControl { return new NetworkTurnControl(connectionControl); } - return super.createTurnControl(playerSettings); + return super.createTurnControl(type); } @Override @@ -71,11 +73,11 @@ public class NetworkRoundControl extends RoundControl { } @Override - protected void endOfTurn(ITable newTable) { + protected void endOfTurn(IHand oldHand, ITable oldTable, ITable newTable) { if (currentlyActive) { - connectionControl.endTurn(newTable); + connectionControl.endTurn(oldHand, oldTable, newTable); } - super.endOfTurn(newTable); + super.endOfTurn(oldHand, oldTable, newTable); } } diff --git a/src/jrummikub/control/network/NetworkTurnControl.java b/src/jrummikub/control/network/NetworkTurnControl.java index d80c9b3..57851a2 100644 --- a/src/jrummikub/control/network/NetworkTurnControl.java +++ b/src/jrummikub/control/network/NetworkTurnControl.java @@ -1,52 +1,56 @@ package jrummikub.control.network; import jrummikub.control.turn.AbstractTurnControl; +import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.Event1; import jrummikub.util.IEvent1; import jrummikub.util.IListener1; +import jrummikub.util.IListener3; public class NetworkTurnControl extends AbstractTurnControl { private IConnectionControl connectionControl; private Event1 stateUpdateEvent = new Event1(); - - + public NetworkTurnControl(IConnectionControl connectionControl) { this.connectionControl = connectionControl; } - + public IEvent1 getStateUpdateEvent() { return stateUpdateEvent; } - + @Override public void doStartTurn() { - connections.add(connectionControl.getTableUpdateEvent().add(new IListener1() { - @Override - public void handle(ITable table) { - view.getTablePanel().setStoneSets(table); - } - })); - connections.add(connectionControl.getTurnEndEvent().add(new IListener1() { - @Override - public void handle(ITable table) { - endOfTurn(table); - } - })); + connections.add(connectionControl.getTableUpdateEvent().add( + new IListener1() { + @Override + public void handle(ITable table) { + view.getTablePanel().setStoneSets(table); + } + })); + connections.add(connectionControl.getTurnEndEvent().add( + new IListener3() { + @Override + public void handle(IHand oldHand, ITable oldTable, ITable newTable) { + endOfTurn(oldHand, oldTable, newTable); + } + })); timer.startTimer(); } - private void endOfTurn(ITable newTable) { + private void endOfTurn(IHand oldHand, ITable oldTable, ITable newTable) { cleanUp(); - endOfTurnEvent.emit(newTable); + + endOfTurnEvent.emit(oldHand, oldTable, newTable); } - + @Override protected void timeOut() { } - + @Override protected void pauseTurn() { } diff --git a/src/jrummikub/control/turn/AIControl.java b/src/jrummikub/control/turn/AIControl.java index 8bcf661..b633f96 100644 --- a/src/jrummikub/control/turn/AIControl.java +++ b/src/jrummikub/control/turn/AIControl.java @@ -225,7 +225,7 @@ public class AIControl extends AbstractTurnControl { return; } cleanUp(); - endOfTurnEvent.emit(turnInfo.getTable()); + endOfTurnEvent.emit(null, null, turnInfo.getTable()); } /** diff --git a/src/jrummikub/control/turn/AbstractTurnControl.java b/src/jrummikub/control/turn/AbstractTurnControl.java index b687ca0..8b481bc 100644 --- a/src/jrummikub/control/turn/AbstractTurnControl.java +++ b/src/jrummikub/control/turn/AbstractTurnControl.java @@ -6,12 +6,15 @@ import java.util.List; import jrummikub.control.ITurnTimer; import jrummikub.control.TurnTimer; import jrummikub.model.GameSettings; +import jrummikub.model.IHand; import jrummikub.model.ITable; import jrummikub.util.Connection; import jrummikub.util.Event; import jrummikub.util.Event1; +import jrummikub.util.Event3; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; +import jrummikub.util.IEvent3; import jrummikub.util.IListener; import jrummikub.view.IView; @@ -19,7 +22,7 @@ import jrummikub.view.IView; * Abstract base class for TurnControls */ public abstract class AbstractTurnControl implements ITurnControl { - protected Event1 endOfTurnEvent = new Event1(); + protected Event3 endOfTurnEvent = new Event3(); protected Event redealEvent = new Event(); protected Event1 tableUpdateEvent = new Event1(); protected TurnInfo turnInfo; @@ -30,7 +33,7 @@ public abstract class AbstractTurnControl implements ITurnControl { private boolean started = false; @Override - public IEvent1 getEndOfTurnEvent() { + public IEvent3 getEndOfTurnEvent() { return endOfTurnEvent; } diff --git a/src/jrummikub/control/turn/HumanTurnControl.java b/src/jrummikub/control/turn/HumanTurnControl.java index 7ca2731..e43ec5b 100644 --- a/src/jrummikub/control/turn/HumanTurnControl.java +++ b/src/jrummikub/control/turn/HumanTurnControl.java @@ -448,7 +448,7 @@ public class HumanTurnControl extends AbstractTurnControl { if (redeal) { redealEvent.emit(); } else { - endOfTurnEvent.emit(turnInfo.getTable()); + endOfTurnEvent.emit(null, null, turnInfo.getTable()); } } diff --git a/src/jrummikub/control/turn/ITurnControl.java b/src/jrummikub/control/turn/ITurnControl.java index 66bd065..5c91c0c 100644 --- a/src/jrummikub/control/turn/ITurnControl.java +++ b/src/jrummikub/control/turn/ITurnControl.java @@ -5,6 +5,7 @@ import jrummikub.model.IHand; import jrummikub.model.ITable; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; +import jrummikub.util.IEvent3; import jrummikub.view.IView; /** @@ -30,7 +31,7 @@ public interface ITurnControl { * * @return end of turn event */ - public IEvent1 getEndOfTurnEvent(); + public IEvent3 getEndOfTurnEvent(); /** * Emitted when the round is aborted and needs to be restarted -- cgit v1.2.3