Implement joining games

git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@434 72836036-5685-4462-b002-a69064685172
This commit is contained in:
Matthias Schiffer 2011-06-14 04:55:24 +02:00
parent 4879b7b93e
commit ebacf1ae74
7 changed files with 269 additions and 15 deletions

View file

@ -7,9 +7,11 @@ import javax.swing.SwingUtilities;
import jrummikub.model.GameSettings; import jrummikub.model.GameSettings;
import jrummikub.util.Event; import jrummikub.util.Event;
import jrummikub.util.Event1; import jrummikub.util.Event1;
import jrummikub.util.Event2;
import jrummikub.util.GameData; import jrummikub.util.GameData;
import jrummikub.util.IEvent; import jrummikub.util.IEvent;
import jrummikub.util.IEvent1; import jrummikub.util.IEvent1;
import jrummikub.util.IEvent2;
import jrummikub.util.LoginData; import jrummikub.util.LoginData;
import org.jivesoftware.smack.Connection; import org.jivesoftware.smack.Connection;
@ -43,6 +45,11 @@ class ConnectionControl {
private Event1<GameData> gameOfferEvent = new Event1<GameData>(); private Event1<GameData> gameOfferEvent = new Event1<GameData>();
private Event1<UUID> gameWithdrawalEvent = new Event1<UUID>(); private Event1<UUID> gameWithdrawalEvent = new Event1<UUID>();
private Event2<UUID, String> gameJoinEvent = new Event2<UUID, String>();
private Event2<UUID, String> gameLeaveEvent = new Event2<UUID, String>();
private Event2<UUID, Boolean> gameJoinAckEvent = new Event2<UUID, Boolean>();
private volatile GameData offeredGame; private volatile GameData offeredGame;
ConnectionControl(LoginData loginData) { ConnectionControl(LoginData loginData) {
@ -80,6 +87,18 @@ class ConnectionControl {
return gameWithdrawalEvent; return gameWithdrawalEvent;
} }
IEvent2<UUID, String> getGameJoinEvent() {
return gameJoinEvent;
}
IEvent2<UUID, String> getGameLeaveEvent() {
return gameLeaveEvent;
}
IEvent2<UUID, Boolean> getGameJoinAckEvent() {
return gameJoinAckEvent;
}
void offerGame(GameData data) { void offerGame(GameData data) {
offeredGame = data; offeredGame = data;
@ -92,6 +111,18 @@ class ConnectionControl {
new Thread(new SendGameWithdrawRunner(uuid)).start(); 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() { private void sendGameOffer() {
new Thread(new SendGameOfferRunner(offeredGame)).start(); new Thread(new SendGameOfferRunner(offeredGame)).start();
} }
@ -119,17 +150,23 @@ class ConnectionControl {
DefaultPacketExtension extension = (DefaultPacketExtension) packet DefaultPacketExtension extension = (DefaultPacketExtension) packet
.getExtension(ELEMENT_NAME, NAMESPACE); .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"); String messageType = extension.getValue("messageType");
if (messageType.equals("game_offer")) { if (messageType.equals("game_offer")) {
String host = packet.getFrom();
host = host.substring(host.indexOf('/') + 1);
UUID uuid = UUID.fromString(extension.getValue("uuid")); UUID uuid = UUID.fromString(extension.getValue("uuid"));
GameSettings settings = (GameSettings) Base64.decodeToObject(extension GameSettings settings = (GameSettings) Base64.decodeToObject(extension
.getValue("gameSettings")); .getValue("gameSettings"));
GameData gameData = new GameData(uuid, settings, host); GameData gameData = new GameData(uuid, settings, sender);
gameOfferEvent.emit(gameData); gameOfferEvent.emit(gameData);
} else if (messageType.equals("game_withdrawal")) { } else if (messageType.equals("game_withdrawal")) {
gameWithdrawalEvent.emit(UUID.fromString(extension.getValue("uuid"))); gameWithdrawalEvent.emit(UUID.fromString(extension.getValue("uuid")));
@ -137,6 +174,16 @@ class ConnectionControl {
if (offeredGame != null) { if (offeredGame != null) {
sendGameOffer(); 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); 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() { private Message createGameRequestMessage() {
DefaultPacketExtension extension = createJRummikubExtension(); 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 { private class DisconnectRunner implements Runnable {
@Override @Override
public void run() { public void run() {

View file

@ -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<Connection> connections = new ArrayList<Connection>();
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<GameData>() {
@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();
}
}
}

View file

@ -1,22 +1,27 @@
package jrummikub.control.network; package jrummikub.control.network;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import jrummikub.model.GameSettings; import jrummikub.model.GameSettings;
import jrummikub.model.PlayerSettings;
import jrummikub.model.PlayerSettings.Type;
import jrummikub.util.Connection;
import jrummikub.util.GameData; import jrummikub.util.GameData;
import jrummikub.util.IListener2;
import jrummikub.view.ISettingsPanel.SettingsMode; import jrummikub.view.ISettingsPanel.SettingsMode;
import jrummikub.view.IView; import jrummikub.view.IView;
public class GameOfferControl { public class GameOfferControl {
private List<Connection> connections = new ArrayList<Connection>();
private GameData gameData; private GameData gameData;
private ConnectionControl connectionControl; private ConnectionControl connectionControl;
private GameSettings settings;
private IView view; private IView view;
public GameOfferControl(ConnectionControl connectionControl, public GameOfferControl(final ConnectionControl connectionControl,
GameSettings settings, IView view) { final GameSettings settings, final IView view) {
this.connectionControl = connectionControl; this.connectionControl = connectionControl;
this.settings = settings;
this.view = view; this.view = view;
gameData = new GameData(UUID.randomUUID(), settings); gameData = new GameData(UUID.randomUUID(), settings);
@ -24,6 +29,29 @@ public class GameOfferControl {
view.getSettingsPanel().setSettingsMode(SettingsMode.NETWORK_OFFER); view.getSettingsPanel().setSettingsMode(SettingsMode.NETWORK_OFFER);
view.getSettingsPanel().enableAddPlayerButton(false); view.getSettingsPanel().enableAddPlayerButton(false);
view.getSettingsPanel().setGameSettings(settings); view.getSettingsPanel().setGameSettings(settings);
connections.add(connectionControl.getGameJoinEvent().add(
new IListener2<UUID, String>() {
@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() { public void startGameOffer() {

View file

@ -13,6 +13,7 @@ import jrummikub.util.GameData;
import jrummikub.util.IEvent; import jrummikub.util.IEvent;
import jrummikub.util.IListener; import jrummikub.util.IListener;
import jrummikub.util.IListener1; import jrummikub.util.IListener1;
import jrummikub.util.IListener2;
import jrummikub.util.LoginData; import jrummikub.util.LoginData;
import jrummikub.view.IView; import jrummikub.view.IView;
@ -27,6 +28,7 @@ public class NetworkControl {
private NetworkSettingsControl settingsControl; private NetworkSettingsControl settingsControl;
private GameOfferControl gameOfferControl; private GameOfferControl gameOfferControl;
private GameJoinControl gameJoinControl;
private Map<UUID, GameData> gameMap = new HashMap<UUID, GameData>(); private Map<UUID, GameData> gameMap = new HashMap<UUID, GameData>();
@ -47,9 +49,8 @@ public class NetworkControl {
connections.add(view.getGameListPanel().getJoinEvent() connections.add(view.getGameListPanel().getJoinEvent()
.add(new IListener1<GameData>() { .add(new IListener1<GameData>() {
@Override @Override
public void handle(GameData value) { public void handle(GameData gameData) {
// TODO Auto-generated method stub 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 * Adds the listeners for connection control events
* *
@ -126,6 +132,29 @@ public class NetworkControl {
} }
} }
})); }));
connections.add(connectionControl.getGameJoinAckEvent().add(
new IListener2<UUID, Boolean>() {
@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) { if (gameOfferControl != null) {
gameOfferControl.abort(); gameOfferControl.abort();
} }
if (gameJoinControl != null) {
gameJoinControl.abort();
}
connectionControl.disconnect(); connectionControl.disconnect();
} }

View file

@ -268,6 +268,8 @@ public interface ISettingsPanel {
/** */ /** */
NETWORK_SETUP, NETWORK_SETUP,
/** */ /** */
NETWORK_OFFER NETWORK_OFFER,
/** */
NETWORK_JOIN
} }
} }

View file

@ -72,8 +72,11 @@ class GameListPanel extends JPanel implements IGameListPanel {
joinButton.addActionListener(new ActionListener() { joinButton.addActionListener(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub Object data = gameList.getSelectedValue();
// joinEvent.emit();
if (data instanceof GameData) {
joinEvent.emit((GameData) data);
}
} }
}); });

View file

@ -373,7 +373,8 @@ class SettingsPanel extends JPanel implements ISettingsPanel {
private void addPlayerSettingsPanel(int i, PlayerSettings settings, private void addPlayerSettingsPanel(int i, PlayerSettings settings,
List<Type> choices) { List<Type> choices) {
PlayerSettingsPanel panel = new PlayerSettingsPanel(i, settings, choices, PlayerSettingsPanel panel = new PlayerSettingsPanel(i, settings, choices,
settingsMode != SettingsMode.NETWORK_OFFER); settingsMode != SettingsMode.NETWORK_OFFER
&& settingsMode != SettingsMode.NETWORK_JOIN);
playerSettingsPanels.add(panel); playerSettingsPanels.add(panel);
playerSettingsViewport.add(panel, playerSettingsViewport.add(panel,
playerSettingsViewport.getComponentCount() - 1); playerSettingsViewport.getComponentCount() - 1);
@ -765,6 +766,10 @@ class SettingsPanel extends JPanel implements ISettingsPanel {
addNetworkOfferButtons(); addNetworkOfferButtons();
enableOptions(false); enableOptions(false);
break; break;
case NETWORK_JOIN:
// addNetworkJoinButtons();
enableOptions(false);
break;
} }
} }