From 630cdea1d9383aee75a984867682459d06c7c61a Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 11 Jun 2011 02:19:23 +0200 Subject: Make game offers, withdrawals (untested) and requests work git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@408 72836036-5685-4462-b002-a69064685172 --- .../control/network/ConnectionControl.java | 233 ++++++++++++++++++--- 1 file changed, 207 insertions(+), 26 deletions(-) (limited to 'src/jrummikub/control/network/ConnectionControl.java') diff --git a/src/jrummikub/control/network/ConnectionControl.java b/src/jrummikub/control/network/ConnectionControl.java index 9777853..171c15d 100644 --- a/src/jrummikub/control/network/ConnectionControl.java +++ b/src/jrummikub/control/network/ConnectionControl.java @@ -1,19 +1,36 @@ package jrummikub.control.network; +import java.util.UUID; + import javax.swing.SwingUtilities; import jrummikub.util.Event; +import jrummikub.util.Event1; import jrummikub.util.IEvent; +import jrummikub.util.IEvent1; import jrummikub.util.LoginData; +import jrummikub.view.IGameListPanel.GameData; import org.jivesoftware.smack.Connection; +import org.jivesoftware.smack.PacketListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.filter.AndFilter; +import org.jivesoftware.smack.filter.PacketExtensionFilter; +import org.jivesoftware.smack.filter.PacketTypeFilter; +import org.jivesoftware.smack.packet.DefaultPacketExtension; +import org.jivesoftware.smack.packet.Message; +import org.jivesoftware.smack.packet.Packet; +import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.XMPPError; import org.jivesoftware.smack.packet.XMPPError.Type; +import org.jivesoftware.smackx.muc.DiscussionHistory; import org.jivesoftware.smackx.muc.MultiUserChat; class ConnectionControl { + private final static String ELEMENT_NAME = "rummikub"; + private final static String NAMESPACE = "http://home.universe-factory.net/rummikub/"; + private final LoginData loginData; private volatile Connection connection; private volatile MultiUserChat muc; @@ -21,6 +38,11 @@ class ConnectionControl { private Event connectedEvent = new Event(); private Event connectionFailedEvent = new Event(); + private Event1 gameOfferEvent = new Event1(); + private Event1 gameWithdrawalEvent = new Event1(); + + private volatile GameData offeredGame; + ConnectionControl(LoginData loginData) { this.loginData = loginData; } @@ -44,6 +66,30 @@ class ConnectionControl { return connectionFailedEvent; } + IEvent1 getGameOfferEvent() { + return gameOfferEvent; + } + + IEvent1 getGameWithdrawalEvent() { + return gameWithdrawalEvent; + } + + void offerGame(GameData data) { + offeredGame = data; + + sendGameOffer(); + } + + void withdrawGame(UUID uuid) { + offeredGame = null; + + new Thread(new SendGameWithdrawRunner(uuid)).start(); + } + + private void sendGameOffer() { + new Thread(new SendGameOfferRunner(offeredGame)).start(); + } + private static void emitLater(final Event event) { SwingUtilities.invokeLater(new Runnable() { @Override @@ -53,40 +99,97 @@ class ConnectionControl { }); } + private Message createMessage(PacketExtension extension) { + Message message = muc.createMessage(); + message.addExtension(extension); + return message; + } + + private static DefaultPacketExtension createJRummikubExtension() { + return new DefaultPacketExtension(ELEMENT_NAME, NAMESPACE); + } + + private void processPacket(Packet packet) { + DefaultPacketExtension extension = (DefaultPacketExtension) packet + .getExtension(ELEMENT_NAME, NAMESPACE); + + 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")); + int currentPlayerCount = Integer.parseInt(extension + .getValue("currentPlayerCount")); + int maxPlayerCount = Integer.parseInt(extension + .getValue("maxPlayerCount")); + + GameData gameData = new GameData(uuid, host); + gameData.setCurrentPlayerCount(currentPlayerCount); + gameData.setMaxPlayerCount(maxPlayerCount); + gameOfferEvent.emit(gameData); + } else if (messageType.equals("game_withdrawal")) { + gameWithdrawalEvent.emit(UUID.fromString(extension.getValue("uuid"))); + } else if (messageType.equals("game_request")) { + if (offeredGame != null) { + sendGameOffer(); + } + } + } + + private Message createGameOfferMessage(GameData data) { + DefaultPacketExtension extension = createJRummikubExtension(); + + extension.setValue("messageType", "game_offer"); + extension.setValue("uuid", data.getGameID().toString()); + extension.setValue("currentPlayerCount", + Integer.toString(data.getCurrentPlayerCount())); + extension.setValue("maxPlayerCount", + Integer.toString(data.getMaxPlayerCount())); + + return createMessage(extension); + } + + private Message createGameWithdrawMessage(UUID uuid) { + DefaultPacketExtension extension = createJRummikubExtension(); + + extension.setValue("messageType", "game_withdrawal"); + extension.setValue("uuid", uuid.toString()); + + return createMessage(extension); + } + + private Message createGameRequestMessage() { + DefaultPacketExtension extension = createJRummikubExtension(); + + extension.setValue("messageType", "game_request"); + + return createMessage(extension); + } + private class ConnectRunner implements Runnable { @Override public void run() { synchronized (ConnectionControl.this) { connection = new XMPPConnection(loginData.getServerName()); - try { - connection.connect(); - connection.login(loginData.getUserName(), - loginData.getPassword(), "JRummikub"); - muc = new MultiUserChat(connection, - loginData.getChannelName()); - - String nickname = loginData.getUserName(); - // Loop until a unused nickname is found - while (true) { - try { - muc.join(nickname); - break; // Join was successful, break the loop - } catch (XMPPException e) { - XMPPError error = e.getXMPPError(); - if (error.getType() == Type.CANCEL - && error.getCode() == 409) { - // There was a conflict, try again with another - // nickname - nickname += "_"; - continue; - } else { - // An unknown error has occurred, cancel connect - throw e; + + connection.addPacketListener(new PacketListener() { + @Override + public void processPacket(final Packet packet) { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + ConnectionControl.this.processPacket(packet); } - } + }); + } + }, new AndFilter(new PacketTypeFilter(Message.class), + new PacketExtensionFilter(ELEMENT_NAME, NAMESPACE))); - emitLater(connectedEvent); + try { + doConnect(); } catch (XMPPException e) { connection.disconnect(); connection = null; @@ -98,6 +201,84 @@ class ConnectionControl { } } } + + private void doConnect() throws XMPPException { + connection.connect(); + connection.login(loginData.getUserName(), loginData.getPassword(), + "JRummikub"); + muc = new MultiUserChat(connection, loginData.getChannelName()); + DiscussionHistory history = new DiscussionHistory(); + history.setMaxStanzas(0); + + String nickname = loginData.getUserName(); + // Loop until a unused nickname is found + while (true) { + try { + muc.join(nickname, null, history, 10000); + break; // Join was successful, break the loop + } catch (XMPPException e) { + XMPPError error = e.getXMPPError(); + if (error.getType() == Type.CANCEL && error.getCode() == 409) { + // There was a conflict, try again with another + // nickname + nickname += "_"; + continue; + } else { + // An unknown error has occurred, cancel connect + throw e; + } + } + } + + emitLater(connectedEvent); + + new Thread(new SendGameRequestRunner()).start(); + } + } + + private class SendGameOfferRunner implements Runnable { + private GameData data; + + public SendGameOfferRunner(GameData data) { + this.data = data; + } + + @Override + public void run() { + synchronized (ConnectionControl.this) { + if (connection != null) { + connection.sendPacket(createGameOfferMessage(data)); + } + } + } + } + + private class SendGameWithdrawRunner implements Runnable { + private UUID uuid; + + public SendGameWithdrawRunner(UUID uuid) { + this.uuid = uuid; + } + + @Override + public void run() { + synchronized (ConnectionControl.this) { + if (connection != null) { + connection.sendPacket(createGameWithdrawMessage(uuid)); + } + } + } + } + + private class SendGameRequestRunner implements Runnable { + @Override + public void run() { + synchronized (ConnectionControl.this) { + if (connection != null) { + connection.sendPacket(createGameRequestMessage()); + } + } + } } private class DisconnectRunner implements Runnable { -- cgit v1.2.3