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
This commit is contained in:
Matthias Schiffer 2011-06-11 02:19:23 +02:00
parent e176dc4608
commit 630cdea1d9
3 changed files with 254 additions and 31 deletions

View file

@ -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<GameData> gameOfferEvent = new Event1<GameData>();
private Event1<UUID> gameWithdrawalEvent = new Event1<UUID>();
private volatile GameData offeredGame;
ConnectionControl(LoginData loginData) {
this.loginData = loginData;
}
@ -44,6 +66,30 @@ class ConnectionControl {
return connectionFailedEvent;
}
IEvent1<GameData> getGameOfferEvent() {
return gameOfferEvent;
}
IEvent1<UUID> 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,28 +99,126 @@ 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());
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)));
try {
doConnect();
} catch (XMPPException e) {
connection.disconnect();
connection = null;
// TODO Auto-generated catch block
e.printStackTrace();
emitLater(connectionFailedEvent);
}
}
}
private void doConnect() throws XMPPException {
connection.connect();
connection.login(loginData.getUserName(),
loginData.getPassword(), "JRummikub");
muc = new MultiUserChat(connection,
loginData.getChannelName());
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);
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) {
if (error.getType() == Type.CANCEL && error.getCode() == 409) {
// There was a conflict, try again with another
// nickname
nickname += "_";
@ -87,14 +231,51 @@ class ConnectionControl {
}
emitLater(connectedEvent);
} catch (XMPPException e) {
connection.disconnect();
connection = null;
// TODO Auto-generated catch block
e.printStackTrace();
new Thread(new SendGameRequestRunner()).start();
}
}
emitLater(connectionFailedEvent);
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());
}
}
}

View file

@ -1,7 +1,9 @@
package jrummikub.control.network;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import jrummikub.util.Connection;
@ -20,6 +22,8 @@ public class NetworkControl {
private List<Connection> connections = new ArrayList<Connection>();
private Event stopNetworkEvent = new Event();
private Map<UUID, GameData> gameMap = new HashMap<UUID, GameData>();
public NetworkControl(final LoginData loginData, final IView view) {
this.view = view;
connectionControl = new ConnectionControl(loginData);
@ -33,7 +37,8 @@ public class NetworkControl {
GameData testData = new GameData(UUID.randomUUID(), "NeoRaider");
testData.setCurrentPlayerCount(2);
testData.setMaxPlayerCount(4);
view.getGameListPanel().addGame(testData);
connectionControl.offerGame(testData);
}
}));
@ -46,6 +51,36 @@ public class NetworkControl {
}
}));
connections.add(connectionControl.getGameOfferEvent().add(
new IListener1<IGameListPanel.GameData>() {
@Override
public void handle(GameData value) {
GameData game = gameMap.get(value.getGameID());
if (game == null) {
game = value;
gameMap.put(value.getGameID(), value);
} else {
game.setCurrentPlayerCount(value.getCurrentPlayerCount());
game.setMaxPlayerCount(value.getMaxPlayerCount());
}
view.getGameListPanel().addGame(game);
}
}));
connections.add(connectionControl.getGameWithdrawalEvent().add(
new IListener1<UUID>() {
@Override
public void handle(UUID value) {
GameData game = gameMap.get(value);
if (game != null) {
view.getGameListPanel().removeGame(game);
gameMap.remove(value);
}
}
}));
connections.add(view.getGameListPanel().getJoinEvent()
.add(new IListener1<IGameListPanel.GameData>() {
@Override

View file

@ -4,7 +4,6 @@ import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
@ -163,16 +162,24 @@ class GameListPanel extends JPanel implements IGameListPanel {
JLabel hostLabel, playerCountLabel;
GameDataCellRenderer() {
setLayout(new GridLayout(1, 2));
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridwidth = 1;
c.weightx = 1;
c.weighty = 1;
hostLabel = new JLabel();
hostLabel.setOpaque(true);
hostLabel.setHorizontalAlignment(JLabel.LEFT);
add(hostLabel);
add(hostLabel, c);
playerCountLabel = new JLabel();
playerCountLabel.setOpaque(true);
playerCountLabel.setHorizontalAlignment(JLabel.RIGHT);
add(playerCountLabel);
c.gridwidth = GridBagConstraints.REMAINDER;
add(playerCountLabel, c);
}
@Override