From ebacf1ae7494abc3a80cf1ec242a6202d6438323 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 14 Jun 2011 04:55:24 +0200 Subject: Implement joining games git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@434 72836036-5685-4462-b002-a69064685172 --- .../control/network/ConnectionControl.java | 141 ++++++++++++++++++++- src/jrummikub/control/network/GameJoinControl.java | 51 ++++++++ .../control/network/GameOfferControl.java | 36 +++++- src/jrummikub/control/network/NetworkControl.java | 38 +++++- src/jrummikub/view/ISettingsPanel.java | 4 +- src/jrummikub/view/impl/GameListPanel.java | 7 +- src/jrummikub/view/impl/SettingsPanel.java | 7 +- 7 files changed, 269 insertions(+), 15 deletions(-) create mode 100644 src/jrummikub/control/network/GameJoinControl.java diff --git a/src/jrummikub/control/network/ConnectionControl.java b/src/jrummikub/control/network/ConnectionControl.java index 7980c2d..d6bb5fe 100644 --- a/src/jrummikub/control/network/ConnectionControl.java +++ b/src/jrummikub/control/network/ConnectionControl.java @@ -7,9 +7,11 @@ import javax.swing.SwingUtilities; import jrummikub.model.GameSettings; import jrummikub.util.Event; import jrummikub.util.Event1; +import jrummikub.util.Event2; import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; +import jrummikub.util.IEvent2; import jrummikub.util.LoginData; import org.jivesoftware.smack.Connection; @@ -43,6 +45,11 @@ class ConnectionControl { private Event1 gameOfferEvent = new Event1(); private Event1 gameWithdrawalEvent = new Event1(); + private Event2 gameJoinEvent = new Event2(); + private Event2 gameLeaveEvent = new Event2(); + + private Event2 gameJoinAckEvent = new Event2(); + private volatile GameData offeredGame; ConnectionControl(LoginData loginData) { @@ -80,6 +87,18 @@ class ConnectionControl { return gameWithdrawalEvent; } + IEvent2 getGameJoinEvent() { + return gameJoinEvent; + } + + IEvent2 getGameLeaveEvent() { + return gameLeaveEvent; + } + + IEvent2 getGameJoinAckEvent() { + return gameJoinAckEvent; + } + void offerGame(GameData data) { offeredGame = data; @@ -92,6 +111,18 @@ class ConnectionControl { new Thread(new SendGameWithdrawRunner(uuid)).start(); } + void joinGame(UUID uuid) { + new Thread(new SendGameJoinRunner(uuid)).start(); + } + + void leaveGame(UUID uuid) { + new Thread(new SendGameLeaveRunner(uuid)).start(); + } + + void ackJoinGame(UUID uuid, String recipient, boolean ack) { + new Thread(new SendGameJoinAckRunner(uuid, recipient, ack)).start(); + } + private void sendGameOffer() { new Thread(new SendGameOfferRunner(offeredGame)).start(); } @@ -119,17 +150,23 @@ class ConnectionControl { DefaultPacketExtension extension = (DefaultPacketExtension) packet .getExtension(ELEMENT_NAME, NAMESPACE); + if (((Message) packet).getType() == Message.Type.error) { + System.err.println("Received error message from '" + packet.getFrom() + + "'"); + return; + } + + String sender = packet.getFrom(); + sender = sender.substring(sender.indexOf('/') + 1); + String messageType = extension.getValue("messageType"); if (messageType.equals("game_offer")) { - String host = packet.getFrom(); - host = host.substring(host.indexOf('/') + 1); - UUID uuid = UUID.fromString(extension.getValue("uuid")); GameSettings settings = (GameSettings) Base64.decodeToObject(extension .getValue("gameSettings")); - GameData gameData = new GameData(uuid, settings, host); + GameData gameData = new GameData(uuid, settings, sender); gameOfferEvent.emit(gameData); } else if (messageType.equals("game_withdrawal")) { gameWithdrawalEvent.emit(UUID.fromString(extension.getValue("uuid"))); @@ -137,6 +174,16 @@ class ConnectionControl { if (offeredGame != null) { sendGameOffer(); } + } else if (messageType.equals("game_join")) { + gameJoinEvent.emit(UUID.fromString(extension.getValue("uuid")), sender); + } else if (messageType.equals("game_leave")) { + gameLeaveEvent.emit(UUID.fromString(extension.getValue("uuid")), sender); + } else if (messageType.equals("game_join_ack")) { + gameJoinAckEvent.emit(UUID.fromString(extension.getValue("uuid")), + Boolean.valueOf(extension.getValue("ack"))); + } else { + System.err.println("Received unrecognized message of type '" + + messageType + "'"); } } @@ -160,6 +207,37 @@ class ConnectionControl { return createMessage(extension); } + private Message createGameJoinMessage(UUID uuid) { + DefaultPacketExtension extension = createJRummikubExtension(); + + extension.setValue("messageType", "game_join"); + extension.setValue("uuid", uuid.toString()); + + return createMessage(extension); + } + + private Message createGameLeaveMessage(UUID uuid) { + DefaultPacketExtension extension = createJRummikubExtension(); + + extension.setValue("messageType", "game_leave"); + extension.setValue("uuid", uuid.toString()); + + return createMessage(extension); + } + + private Message createGameAckMessage(UUID uuid, String recipient, boolean ack) { + DefaultPacketExtension extension = createJRummikubExtension(); + + extension.setValue("messageType", "game_join_ack"); + extension.setValue("uuid", uuid.toString()); + extension.setValue("ack", Boolean.toString(ack)); + + Message message = createMessage(extension); + message.setType(Message.Type.normal); + message.setTo(muc.getRoom() + "/" + recipient); + return message; + } + private Message createGameRequestMessage() { DefaultPacketExtension extension = createJRummikubExtension(); @@ -281,6 +359,61 @@ class ConnectionControl { } } + private class SendGameJoinRunner implements Runnable { + private UUID uuid; + + public SendGameJoinRunner(UUID uuid) { + this.uuid = uuid; + } + + @Override + public void run() { + synchronized (ConnectionControl.this) { + if (connection != null) { + connection.sendPacket(createGameJoinMessage(uuid)); + } + } + } + } + + private class SendGameLeaveRunner implements Runnable { + private UUID uuid; + + public SendGameLeaveRunner(UUID uuid) { + this.uuid = uuid; + } + + @Override + public void run() { + synchronized (ConnectionControl.this) { + if (connection != null) { + connection.sendPacket(createGameLeaveMessage(uuid)); + } + } + } + } + + private class SendGameJoinAckRunner implements Runnable { + private UUID uuid; + private String recipient; + private boolean ack; + + public SendGameJoinAckRunner(UUID uuid, String recipient, boolean ack) { + this.uuid = uuid; + this.recipient = recipient; + this.ack = ack; + } + + @Override + public void run() { + synchronized (ConnectionControl.this) { + if (connection != null) { + connection.sendPacket(createGameAckMessage(uuid, recipient, ack)); + } + } + } + } + private class DisconnectRunner implements Runnable { @Override public void run() { diff --git a/src/jrummikub/control/network/GameJoinControl.java b/src/jrummikub/control/network/GameJoinControl.java new file mode 100644 index 0000000..c436887 --- /dev/null +++ b/src/jrummikub/control/network/GameJoinControl.java @@ -0,0 +1,51 @@ +package jrummikub.control.network; + +import java.util.ArrayList; +import java.util.List; + +import jrummikub.util.Connection; +import jrummikub.util.GameData; +import jrummikub.util.IListener1; +import jrummikub.view.ISettingsPanel.SettingsMode; +import jrummikub.view.IView; + +public class GameJoinControl { + private List connections = new ArrayList(); + private GameData gameData; + private ConnectionControl connectionControl; + private IView view; + + public GameJoinControl(final ConnectionControl connectionControl, + final GameData gameData, final IView view) { + this.connectionControl = connectionControl; + this.gameData = gameData; + this.view = view; + + view.getSettingsPanel().setSettingsMode(SettingsMode.NETWORK_JOIN); + view.getSettingsPanel().enableAddPlayerButton(false); + view.getSettingsPanel().setGameSettings(gameData.getGameSettings()); + + connections.add(connectionControl.getGameOfferEvent().add( + new IListener1() { + @Override + public void handle(GameData data) { + if (data.getGameID().equals(gameData.getGameID())) { + gameData.setGameSettings(data.getGameSettings()); + view.getSettingsPanel().setGameSettings(data.getGameSettings()); + } + } + })); + } + + public void startGameJoin() { + view.showSettingsPanel(true); + } + + public void abort() { + // TODO Implement abort + + for (Connection c : connections) { + c.remove(); + } + } +} diff --git a/src/jrummikub/control/network/GameOfferControl.java b/src/jrummikub/control/network/GameOfferControl.java index 0db5110..7cd289f 100644 --- a/src/jrummikub/control/network/GameOfferControl.java +++ b/src/jrummikub/control/network/GameOfferControl.java @@ -1,22 +1,27 @@ package jrummikub.control.network; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import jrummikub.model.GameSettings; +import jrummikub.model.PlayerSettings; +import jrummikub.model.PlayerSettings.Type; +import jrummikub.util.Connection; import jrummikub.util.GameData; +import jrummikub.util.IListener2; import jrummikub.view.ISettingsPanel.SettingsMode; import jrummikub.view.IView; public class GameOfferControl { + private List connections = new ArrayList(); private GameData gameData; private ConnectionControl connectionControl; - private GameSettings settings; private IView view; - public GameOfferControl(ConnectionControl connectionControl, - GameSettings settings, IView view) { + public GameOfferControl(final ConnectionControl connectionControl, + final GameSettings settings, final IView view) { this.connectionControl = connectionControl; - this.settings = settings; this.view = view; gameData = new GameData(UUID.randomUUID(), settings); @@ -24,6 +29,29 @@ public class GameOfferControl { view.getSettingsPanel().setSettingsMode(SettingsMode.NETWORK_OFFER); view.getSettingsPanel().enableAddPlayerButton(false); view.getSettingsPanel().setGameSettings(settings); + + connections.add(connectionControl.getGameJoinEvent().add( + new IListener2() { + @Override + public void handle(UUID uuid, String sender) { + if (!uuid.equals(gameData.getGameID())) { + return; + } + + for (PlayerSettings player : settings.getPlayerList()) { + if (player.getType() == Type.VACANT) { + player.setName(sender); + player.setType(Type.NETWORK); + view.getSettingsPanel().setGameSettings(settings); + connectionControl.ackJoinGame(uuid, sender, true); + connectionControl.offerGame(gameData); + return; + } + } + + connectionControl.ackJoinGame(uuid, sender, false); + } + })); } public void startGameOffer() { diff --git a/src/jrummikub/control/network/NetworkControl.java b/src/jrummikub/control/network/NetworkControl.java index 7435839..dd4a949 100644 --- a/src/jrummikub/control/network/NetworkControl.java +++ b/src/jrummikub/control/network/NetworkControl.java @@ -13,6 +13,7 @@ import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IListener; import jrummikub.util.IListener1; +import jrummikub.util.IListener2; import jrummikub.util.LoginData; import jrummikub.view.IView; @@ -27,6 +28,7 @@ public class NetworkControl { private NetworkSettingsControl settingsControl; private GameOfferControl gameOfferControl; + private GameJoinControl gameJoinControl; private Map gameMap = new HashMap(); @@ -47,9 +49,8 @@ public class NetworkControl { connections.add(view.getGameListPanel().getJoinEvent() .add(new IListener1() { @Override - public void handle(GameData value) { - // TODO Auto-generated method stub - + public void handle(GameData gameData) { + join(gameData); } })); @@ -71,6 +72,11 @@ public class NetworkControl { })); } + private void join(GameData gameData) { + view.showGameListPanel(false); + connectionControl.joinGame(gameData.getGameID()); + } + /** * Adds the listeners for connection control events * @@ -126,6 +132,29 @@ public class NetworkControl { } } })); + connections.add(connectionControl.getGameJoinAckEvent().add( + new IListener2() { + @Override + public void handle(UUID uuid, Boolean ack) { + if (ack) { + createGameJoinControl(uuid); + } else { + // TODO Error message + System.err.println("Join NACKed"); + view.showGameListPanel(true); + } + } + })); + } + + private void createGameJoinControl(UUID uuid) { + if (gameJoinControl != null) { + return; + } + + GameData gameData = gameMap.get(uuid); + gameJoinControl = new GameJoinControl(connectionControl, gameData, view); + gameJoinControl.startGameJoin(); } /** @@ -150,6 +179,9 @@ public class NetworkControl { if (gameOfferControl != null) { gameOfferControl.abort(); } + if (gameJoinControl != null) { + gameJoinControl.abort(); + } connectionControl.disconnect(); } diff --git a/src/jrummikub/view/ISettingsPanel.java b/src/jrummikub/view/ISettingsPanel.java index c2bd766..279526a 100644 --- a/src/jrummikub/view/ISettingsPanel.java +++ b/src/jrummikub/view/ISettingsPanel.java @@ -268,6 +268,8 @@ public interface ISettingsPanel { /** */ NETWORK_SETUP, /** */ - NETWORK_OFFER + NETWORK_OFFER, + /** */ + NETWORK_JOIN } } \ No newline at end of file diff --git a/src/jrummikub/view/impl/GameListPanel.java b/src/jrummikub/view/impl/GameListPanel.java index 7324559..2d07f2e 100644 --- a/src/jrummikub/view/impl/GameListPanel.java +++ b/src/jrummikub/view/impl/GameListPanel.java @@ -72,8 +72,11 @@ class GameListPanel extends JPanel implements IGameListPanel { joinButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - // TODO Auto-generated method stub - // joinEvent.emit(); + Object data = gameList.getSelectedValue(); + + if (data instanceof GameData) { + joinEvent.emit((GameData) data); + } } }); diff --git a/src/jrummikub/view/impl/SettingsPanel.java b/src/jrummikub/view/impl/SettingsPanel.java index 8ec9d3e..c7b6387 100644 --- a/src/jrummikub/view/impl/SettingsPanel.java +++ b/src/jrummikub/view/impl/SettingsPanel.java @@ -373,7 +373,8 @@ class SettingsPanel extends JPanel implements ISettingsPanel { private void addPlayerSettingsPanel(int i, PlayerSettings settings, List choices) { PlayerSettingsPanel panel = new PlayerSettingsPanel(i, settings, choices, - settingsMode != SettingsMode.NETWORK_OFFER); + settingsMode != SettingsMode.NETWORK_OFFER + && settingsMode != SettingsMode.NETWORK_JOIN); playerSettingsPanels.add(panel); playerSettingsViewport.add(panel, playerSettingsViewport.getComponentCount() - 1); @@ -765,6 +766,10 @@ class SettingsPanel extends JPanel implements ISettingsPanel { addNetworkOfferButtons(); enableOptions(false); break; + case NETWORK_JOIN: + // addNetworkJoinButtons(); + enableOptions(false); + break; } } -- cgit v1.2.3