mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
- Remove old net code
- Remove "Start/Stop Server" buttons (related to old code) - Move new net code to forge-gui/forge/net/** - Remove all dependencies on project forge-net
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
package forge.interfaces;
|
||||
|
||||
import forge.match.GameLobby;
|
||||
import forge.net.game.server.RemoteClient;
|
||||
import forge.net.server.RemoteClient;
|
||||
|
||||
public interface ILobby {
|
||||
GameLobby getState();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package forge.interfaces;
|
||||
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.net.event.UpdateLobbyPlayerEvent;
|
||||
|
||||
public interface IPlayerChangeListener {
|
||||
void update(int index, UpdateLobbyPlayerEvent event);
|
||||
|
||||
@@ -30,8 +30,7 @@ import forge.interfaces.IGuiGame;
|
||||
import forge.interfaces.IUpdateable;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.net.game.LobbySlotType;
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.net.event.UpdateLobbyPlayerEvent;
|
||||
import forge.player.GamePlayerUtil;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.util.NameGenerator;
|
||||
|
||||
@@ -7,8 +7,7 @@ import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import forge.AIOption;
|
||||
import forge.deck.Deck;
|
||||
import forge.net.game.LobbySlotType;
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.net.event.UpdateLobbyPlayerEvent;
|
||||
|
||||
public final class LobbySlot implements Serializable {
|
||||
private static final long serialVersionUID = 6918205436608794289L;
|
||||
|
||||
8
forge-gui/src/main/java/forge/match/LobbySlotType.java
Normal file
8
forge-gui/src/main/java/forge/match/LobbySlotType.java
Normal file
@@ -0,0 +1,8 @@
|
||||
package forge.match;
|
||||
|
||||
public enum LobbySlotType {
|
||||
LOCAL,
|
||||
AI,
|
||||
OPEN,
|
||||
REMOTE;
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import java.util.Collections;
|
||||
import forge.AIOption;
|
||||
import forge.GuiBase;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.net.game.LobbySlotType;
|
||||
|
||||
public final class LocalLobby extends GameLobby {
|
||||
|
||||
|
||||
@@ -1,398 +0,0 @@
|
||||
package forge.net;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.UiCommand;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.CardPool;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.GameView;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.interfaces.IButton;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.interfaces.ILobbyListener;
|
||||
import forge.match.MatchButtonType;
|
||||
import forge.model.FModel;
|
||||
import forge.net.game.GuiGameEvent;
|
||||
import forge.net.game.IdentifiableNetEvent;
|
||||
import forge.net.game.LoginEvent;
|
||||
import forge.net.game.MessageEvent;
|
||||
import forge.net.game.NetEvent;
|
||||
import forge.net.game.ReplyEvent;
|
||||
import forge.net.game.client.IToServer;
|
||||
import forge.player.PlayerZoneUpdates;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.util.ITriggerEvent;
|
||||
|
||||
public class FGameClient implements IToServer {
|
||||
private final IGuiGame clientGui;
|
||||
public FGameClient(final String username, final String roomKey, final IGuiGame clientGui) {
|
||||
this.clientGui = clientGui;
|
||||
}
|
||||
|
||||
private final List<ILobbyListener> lobbyListeners = Lists.newArrayList();
|
||||
private final ReplyPool replies = new ReplyPool();
|
||||
|
||||
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
||||
|
||||
private Channel channel;
|
||||
public void connect(final String host, final int port) {
|
||||
final EventLoopGroup group = new NioEventLoopGroup();
|
||||
try {
|
||||
final Bootstrap b = new Bootstrap()
|
||||
.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(final SocketChannel ch) throws Exception {
|
||||
final ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||
new MessageHandler(),
|
||||
new LobbyUpdateHandler(),
|
||||
new GameClientHandler());
|
||||
}
|
||||
});
|
||||
|
||||
// Start the connection attempt.
|
||||
channel = b.connect(host, port).sync().channel();
|
||||
final ChannelFuture ch = channel.closeFuture();
|
||||
new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
ch.sync();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final NetEvent event) {
|
||||
System.out.println("Client sent " + event);
|
||||
channel.writeAndFlush(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException {
|
||||
replies.initialize(event.getId());
|
||||
|
||||
send(event);
|
||||
|
||||
// Wait for reply
|
||||
return replies.get(event.getId());
|
||||
}
|
||||
|
||||
public void addLobbyListener(final ILobbyListener listener) {
|
||||
lobbyListeners.add(listener);
|
||||
}
|
||||
|
||||
private void setGameControllers(final Iterable<PlayerView> myPlayers) {
|
||||
for (final PlayerView p : myPlayers) {
|
||||
clientGui.setGameController(p, new NetGameController(this));
|
||||
}
|
||||
}
|
||||
|
||||
private class GameClientHandler extends ChannelInboundHandlerAdapter {
|
||||
/**
|
||||
* Creates a client-side handler.
|
||||
*/
|
||||
public GameClientHandler() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext ctx) {
|
||||
// Don't use send() here, as this.channel is not yet set!
|
||||
ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0])));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
||||
System.out.println("Client received: " + msg);
|
||||
if (msg instanceof ReplyEvent) {
|
||||
final ReplyEvent event = (ReplyEvent) msg;
|
||||
replies.complete(event.getIndex(), event.getReply());
|
||||
} else if (msg instanceof GuiGameEvent) {
|
||||
final GuiGameEvent event = (GuiGameEvent) msg;
|
||||
final String method = event.getMethod();
|
||||
final Object[] args = event.getObjects();
|
||||
Serializable reply = null;
|
||||
boolean doReply = false;
|
||||
|
||||
final IButton btn;
|
||||
if (method.startsWith("btn_") && args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) {
|
||||
btn = args[1] == MatchButtonType.OK ? clientGui.getBtnOK((PlayerView) args[0]) : clientGui.getBtnCancel((PlayerView) args[0]);
|
||||
} else {
|
||||
btn = null;
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case "setGameView":
|
||||
clientGui.setGameView((GameView) args[0]);
|
||||
break;
|
||||
case "openView":
|
||||
final TrackableCollection<PlayerView> myPlayers = (TrackableCollection<PlayerView>) args[0];
|
||||
setGameControllers(myPlayers);
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
//clientGui.setGameView(new NetGameView(FGameClient.this));
|
||||
clientGui.openView(myPlayers);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "afterGameEnd":
|
||||
clientGui.afterGameEnd();
|
||||
break;
|
||||
case "showCombat":
|
||||
clientGui.showCombat();
|
||||
break;
|
||||
case "showPromptMessage":
|
||||
clientGui.showPromptMessage((PlayerView) args[0], (String) args[1]);
|
||||
break;
|
||||
case "stopAtPhase":
|
||||
reply = clientGui.stopAtPhase((PlayerView) args[0], (PhaseType) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "focusButton":
|
||||
clientGui.focusButton((MatchButtonType) args[0]);
|
||||
break;
|
||||
case "flashIncorrectAction":
|
||||
clientGui.flashIncorrectAction();
|
||||
break;
|
||||
case "updatePhase":
|
||||
clientGui.updatePhase();
|
||||
break;
|
||||
case "updateTurn":
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
clientGui.updateTurn((PlayerView) args[0]);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "udpdatePlayerControl":
|
||||
clientGui.updatePlayerControl();
|
||||
break;
|
||||
case "enableOverlay":
|
||||
clientGui.enableOverlay();
|
||||
break;
|
||||
case "disbleOverlay":
|
||||
clientGui.disableOverlay();
|
||||
break;
|
||||
case "finishGame":
|
||||
clientGui.finishGame();
|
||||
break;
|
||||
case "showManaPool":
|
||||
clientGui.showManaPool((PlayerView) args[0]);
|
||||
break;
|
||||
case "hideManaPool":
|
||||
clientGui.hideManaPool((PlayerView) args[0], args[1]);
|
||||
break;
|
||||
case "updateStack":
|
||||
clientGui.updateStack();
|
||||
break;
|
||||
case "updateZones":
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
clientGui.updateZones((PlayerZoneUpdates) args[0]);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "updateSingleCard":
|
||||
clientGui.updateSingleCard((CardView) args[0]);
|
||||
break;
|
||||
case "updateManaPool":
|
||||
clientGui.updateManaPool((Iterable<PlayerView>) args[0]);
|
||||
break;
|
||||
case "updateLives":
|
||||
clientGui.updateLives((Iterable<PlayerView>) args[0]);
|
||||
break;
|
||||
case "setPanelSelection":
|
||||
clientGui.setPanelSelection((CardView) args[0]);
|
||||
break;
|
||||
case "getAbilityToPlay":
|
||||
reply = clientGui.getAbilityToPlay((List<SpellAbilityView>) args[0], (ITriggerEvent) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "assignDamage":
|
||||
reply = (Serializable) clientGui.assignDamage((CardView) args[0], (List<CardView>) args[1], (int) args[2], (GameEntityView) args[3], (boolean) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "message":
|
||||
clientGui.message((String) args[0], (String) args[1]);
|
||||
break;
|
||||
case "showErrorDialog":
|
||||
clientGui.showErrorDialog((String) args[0], (String) args[1]);
|
||||
break;
|
||||
case "showConfirmDialog":
|
||||
reply = clientGui.showConfirmDialog((String) args[0], (String) args[1], (String) args[2], (String) args[3], (boolean) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "showOptionDialog":
|
||||
reply = clientGui.showOptionDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String[]) args[3], (int) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "showCardOptionDialog":
|
||||
reply = clientGui.showCardOptionDialog((CardView) args[0], (String) args[1], (String) args[2], (FSkinProp) args[3], (String[]) args[4], (int) args[5]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "showInputDialog":
|
||||
reply = clientGui.showInputDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String) args[3], (String[]) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "confirm":
|
||||
reply = clientGui.confirm((CardView) args[0], (String) args[1], (boolean) args[2], (String[]) args[3]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "getChoices":
|
||||
reply = (Serializable) clientGui.getChoices((String) args[0], (int) args[1], (int) args[2], (Collection<Object>) args[3], args[4], (Function<Object, String>) args[5]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "order":
|
||||
reply = (Serializable) clientGui.order((String) args[0], (String) args[1], (int) args[2], (int) args[3], (List<Object>) args[4], (List<Object>) args[5], (CardView) args[6], (boolean) args[7]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "sideboard":
|
||||
reply = (Serializable) clientGui.sideboard((CardPool) args[0], (CardPool) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "chooseSingleEntityForEffect":
|
||||
reply = clientGui.chooseSingleEntityForEffect((String) args[0], (TrackableCollection<GameEntityView>) args[1], (DelayedReveal) args[2], (boolean) args[3]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "setCard":
|
||||
clientGui.setCard((CardView) args[0]);
|
||||
break;
|
||||
// TODO case "setPlayerAvatar":
|
||||
case "openZones":
|
||||
reply = clientGui.openZones((Collection<ZoneType>) args[0], (Map<PlayerView, Object>) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "restoreOldZones":
|
||||
clientGui.restoreOldZones((Map<PlayerView, Object>) args[0]);
|
||||
break;
|
||||
case "isUiSetToSkipPhase":
|
||||
reply = clientGui.isUiSetToSkipPhase((PlayerView) args[0], (PhaseType) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
// BUTTONS
|
||||
case "btn_setEnabled":
|
||||
btn.setEnabled((boolean) args[2]);
|
||||
break;
|
||||
case "btn_setVisible":
|
||||
btn.setVisible((boolean) args[2]);
|
||||
break;
|
||||
case "btn_setText":
|
||||
btn.setText((String) args[2]);
|
||||
break;
|
||||
case "btn_isSelected":
|
||||
reply = btn.isSelected();
|
||||
doReply = true;
|
||||
break;
|
||||
case "btn_setSelected":
|
||||
btn.setSelected((boolean) args[2]);
|
||||
break;
|
||||
case "btn_requestFocusInWindows":
|
||||
reply = btn.requestFocusInWindow();
|
||||
doReply = true;
|
||||
break;
|
||||
case "btn_setCommand":
|
||||
btn.setCommand((UiCommand) args[2]);
|
||||
break;
|
||||
case "btn_setTextColor":
|
||||
if (args.length == 3) {
|
||||
btn.setTextColor((FSkinProp) args[2]);
|
||||
} else {
|
||||
btn.setTextColor((int) args[2], (int) args[3], (int) args[4]);
|
||||
}
|
||||
default:
|
||||
System.err.println("Unsupported game event " + event.getMethod());
|
||||
break;
|
||||
}
|
||||
if (doReply) {
|
||||
send(new ReplyEvent(event.getId(), reply));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageHandler extends ChannelInboundHandlerAdapter {
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
if (msg instanceof MessageEvent) {
|
||||
final MessageEvent event = (MessageEvent) msg;
|
||||
for (final ILobbyListener listener : lobbyListeners) {
|
||||
listener.message(event.getSource(), event.getMessage());
|
||||
}
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class LobbyUpdateHandler extends ChannelInboundHandlerAdapter {
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
if (msg instanceof LobbyUpdateEvent) {
|
||||
for (final ILobbyListener listener : lobbyListeners) {
|
||||
final LobbyUpdateEvent event = (LobbyUpdateEvent) msg;
|
||||
listener.update(event.getState(), event.getSlot());
|
||||
}
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
||||
for (final ILobbyListener listener : lobbyListeners) {
|
||||
listener.close();
|
||||
}
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
forge-gui/src/main/java/forge/net/IRemote.java
Normal file
11
forge-gui/src/main/java/forge/net/IRemote.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package forge.net;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import forge.net.event.IdentifiableNetEvent;
|
||||
import forge.net.event.NetEvent;
|
||||
|
||||
public interface IRemote {
|
||||
void send(NetEvent event);
|
||||
Object sendAndWait(IdentifiableNetEvent event) throws TimeoutException;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package forge.net;
|
||||
|
||||
import forge.match.GameLobby.GameLobbyData;
|
||||
import forge.net.game.NetEvent;
|
||||
import forge.net.game.server.RemoteClient;
|
||||
|
||||
public class LobbyUpdateEvent implements NetEvent {
|
||||
private static final long serialVersionUID = 7114918637727047985L;
|
||||
|
||||
private final GameLobbyData state;
|
||||
private int slot;
|
||||
public LobbyUpdateEvent(final GameLobbyData state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateForClient(final RemoteClient client) {
|
||||
this.slot = client.getIndex();
|
||||
}
|
||||
|
||||
public GameLobbyData getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
public int getSlot() {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
57
forge-gui/src/main/java/forge/net/ReplyPool.java
Normal file
57
forge-gui/src/main/java/forge/net/ReplyPool.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package forge.net;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
public class ReplyPool {
|
||||
|
||||
private final Map<Integer, CompletableFuture> pool = Maps.newHashMap();
|
||||
|
||||
public ReplyPool() {
|
||||
}
|
||||
|
||||
public void initialize(final int index) {
|
||||
synchronized (pool) {
|
||||
pool.put(Integer.valueOf(index), new CompletableFuture());
|
||||
}
|
||||
}
|
||||
|
||||
public void complete(final int index, final Object value) {
|
||||
synchronized (pool) {
|
||||
pool.get(Integer.valueOf(index)).set(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Object get(final int index) throws TimeoutException {
|
||||
final CompletableFuture future;
|
||||
synchronized (pool) {
|
||||
future = pool.get(Integer.valueOf(index));
|
||||
}
|
||||
try {
|
||||
return future.get(1, TimeUnit.MINUTES);
|
||||
} catch (final InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class CompletableFuture extends FutureTask<Object> {
|
||||
public CompletableFuture() {
|
||||
super(new Callable<Object>() {
|
||||
@Override public Object call() throws Exception {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(final Object v) {
|
||||
super.set(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge.net;
|
||||
package forge.net.client;
|
||||
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.match.GameLobby;
|
||||
151
forge-gui/src/main/java/forge/net/client/FGameClient.java
Normal file
151
forge-gui/src/main/java/forge/net/client/FGameClient.java
Normal file
@@ -0,0 +1,151 @@
|
||||
package forge.net.client;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.interfaces.ILobbyListener;
|
||||
import forge.net.ReplyPool;
|
||||
import forge.net.event.IdentifiableNetEvent;
|
||||
import forge.net.event.LobbyUpdateEvent;
|
||||
import forge.net.event.MessageEvent;
|
||||
import forge.net.event.NetEvent;
|
||||
|
||||
public class FGameClient implements IToServer {
|
||||
|
||||
private final IGuiGame clientGui;
|
||||
private final List<ILobbyListener> lobbyListeners = Lists.newArrayList();
|
||||
private final ReplyPool replies = new ReplyPool();
|
||||
private Channel channel;
|
||||
|
||||
public FGameClient(final String username, final String roomKey, final IGuiGame clientGui) {
|
||||
this.clientGui = clientGui;
|
||||
}
|
||||
|
||||
final IGuiGame getGui() {
|
||||
return clientGui;
|
||||
}
|
||||
final ReplyPool getReplyPool() {
|
||||
return replies;
|
||||
}
|
||||
|
||||
public void connect(final String host, final int port) {
|
||||
final EventLoopGroup group = new NioEventLoopGroup();
|
||||
try {
|
||||
final Bootstrap b = new Bootstrap()
|
||||
.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(final SocketChannel ch) throws Exception {
|
||||
final ChannelPipeline pipeline = ch.pipeline();
|
||||
pipeline.addLast(
|
||||
new ObjectEncoder(),
|
||||
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||
new MessageHandler(),
|
||||
new LobbyUpdateHandler(),
|
||||
new GameClientHandler(FGameClient.this));
|
||||
}
|
||||
});
|
||||
|
||||
// Start the connection attempt.
|
||||
channel = b.connect(host, port).sync().channel();
|
||||
final ChannelFuture ch = channel.closeFuture();
|
||||
new Thread(new Runnable() {
|
||||
@Override public void run() {
|
||||
try {
|
||||
ch.sync();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
channel.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final NetEvent event) {
|
||||
System.out.println("Client sent " + event);
|
||||
channel.writeAndFlush(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException {
|
||||
replies.initialize(event.getId());
|
||||
|
||||
send(event);
|
||||
|
||||
// Wait for reply
|
||||
return replies.get(event.getId());
|
||||
}
|
||||
|
||||
public void addLobbyListener(final ILobbyListener listener) {
|
||||
lobbyListeners.add(listener);
|
||||
}
|
||||
|
||||
void setGameControllers(final Iterable<PlayerView> myPlayers) {
|
||||
for (final PlayerView p : myPlayers) {
|
||||
clientGui.setGameController(p, new NetGameController(this));
|
||||
}
|
||||
}
|
||||
|
||||
private class MessageHandler extends ChannelInboundHandlerAdapter {
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
if (msg instanceof MessageEvent) {
|
||||
final MessageEvent event = (MessageEvent) msg;
|
||||
for (final ILobbyListener listener : lobbyListeners) {
|
||||
listener.message(event.getSource(), event.getMessage());
|
||||
}
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class LobbyUpdateHandler extends ChannelInboundHandlerAdapter {
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||
if (msg instanceof LobbyUpdateEvent) {
|
||||
for (final ILobbyListener listener : lobbyListeners) {
|
||||
final LobbyUpdateEvent event = (LobbyUpdateEvent) msg;
|
||||
listener.update(event.getState(), event.getSlot());
|
||||
}
|
||||
}
|
||||
super.channelRead(ctx, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
||||
for (final ILobbyListener listener : lobbyListeners) {
|
||||
listener.close();
|
||||
}
|
||||
super.channelInactive(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
268
forge-gui/src/main/java/forge/net/client/GameClientHandler.java
Normal file
268
forge-gui/src/main/java/forge/net/client/GameClientHandler.java
Normal file
@@ -0,0 +1,268 @@
|
||||
package forge.net.client;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.UiCommand;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.deck.CardPool;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.GameView;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.interfaces.IButton;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.match.MatchButtonType;
|
||||
import forge.model.FModel;
|
||||
import forge.net.event.GuiGameEvent;
|
||||
import forge.net.event.LoginEvent;
|
||||
import forge.net.event.ReplyEvent;
|
||||
import forge.player.PlayerZoneUpdates;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.util.ITriggerEvent;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
||||
class GameClientHandler extends ChannelInboundHandlerAdapter {
|
||||
private final FGameClient client;
|
||||
private final IGuiGame gui;
|
||||
|
||||
/**
|
||||
* Creates a client-side game handler.
|
||||
*/
|
||||
public GameClientHandler(final FGameClient client) {
|
||||
this.client = client;
|
||||
this.gui = client.getGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext ctx) {
|
||||
// Don't use send() here, as this.channel is not yet set!
|
||||
ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0])));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
||||
System.out.println("Client received: " + msg);
|
||||
if (msg instanceof ReplyEvent) {
|
||||
final ReplyEvent event = (ReplyEvent) msg;
|
||||
client.getReplyPool().complete(event.getIndex(), event.getReply());
|
||||
} else if (msg instanceof GuiGameEvent) {
|
||||
final GuiGameEvent event = (GuiGameEvent) msg;
|
||||
final String method = event.getMethod();
|
||||
final Object[] args = event.getObjects();
|
||||
Serializable reply = null;
|
||||
boolean doReply = false;
|
||||
|
||||
final IButton btn;
|
||||
if (method.startsWith("btn_") && args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) {
|
||||
btn = args[1] == MatchButtonType.OK ? gui.getBtnOK((PlayerView) args[0]) : gui.getBtnCancel((PlayerView) args[0]);
|
||||
} else {
|
||||
btn = null;
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case "setGameView":
|
||||
gui.setGameView((GameView) args[0]);
|
||||
break;
|
||||
case "openView":
|
||||
final TrackableCollection<PlayerView> myPlayers = (TrackableCollection<PlayerView>) args[0];
|
||||
client.setGameControllers(myPlayers);
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
gui.openView(myPlayers);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "afterGameEnd":
|
||||
gui.afterGameEnd();
|
||||
break;
|
||||
case "showCombat":
|
||||
gui.showCombat();
|
||||
break;
|
||||
case "showPromptMessage":
|
||||
gui.showPromptMessage((PlayerView) args[0], (String) args[1]);
|
||||
break;
|
||||
case "stopAtPhase":
|
||||
reply = gui.stopAtPhase((PlayerView) args[0], (PhaseType) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "focusButton":
|
||||
gui.focusButton((MatchButtonType) args[0]);
|
||||
break;
|
||||
case "flashIncorrectAction":
|
||||
gui.flashIncorrectAction();
|
||||
break;
|
||||
case "updatePhase":
|
||||
gui.updatePhase();
|
||||
break;
|
||||
case "updateTurn":
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
gui.updateTurn((PlayerView) args[0]);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "udpdatePlayerControl":
|
||||
gui.updatePlayerControl();
|
||||
break;
|
||||
case "enableOverlay":
|
||||
gui.enableOverlay();
|
||||
break;
|
||||
case "disbleOverlay":
|
||||
gui.disableOverlay();
|
||||
break;
|
||||
case "finishGame":
|
||||
gui.finishGame();
|
||||
break;
|
||||
case "showManaPool":
|
||||
gui.showManaPool((PlayerView) args[0]);
|
||||
break;
|
||||
case "hideManaPool":
|
||||
gui.hideManaPool((PlayerView) args[0], args[1]);
|
||||
break;
|
||||
case "updateStack":
|
||||
gui.updateStack();
|
||||
break;
|
||||
case "updateZones":
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
gui.updateZones((PlayerZoneUpdates) args[0]);
|
||||
}
|
||||
});
|
||||
break;
|
||||
case "updateSingleCard":
|
||||
gui.updateSingleCard((CardView) args[0]);
|
||||
break;
|
||||
case "updateManaPool":
|
||||
gui.updateManaPool((Iterable<PlayerView>) args[0]);
|
||||
break;
|
||||
case "updateLives":
|
||||
gui.updateLives((Iterable<PlayerView>) args[0]);
|
||||
break;
|
||||
case "setPanelSelection":
|
||||
gui.setPanelSelection((CardView) args[0]);
|
||||
break;
|
||||
case "getAbilityToPlay":
|
||||
reply = gui.getAbilityToPlay((List<SpellAbilityView>) args[0], (ITriggerEvent) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "assignDamage":
|
||||
reply = (Serializable) gui.assignDamage((CardView) args[0], (List<CardView>) args[1], (int) args[2], (GameEntityView) args[3], (boolean) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "message":
|
||||
gui.message((String) args[0], (String) args[1]);
|
||||
break;
|
||||
case "showErrorDialog":
|
||||
gui.showErrorDialog((String) args[0], (String) args[1]);
|
||||
break;
|
||||
case "showConfirmDialog":
|
||||
reply = gui.showConfirmDialog((String) args[0], (String) args[1], (String) args[2], (String) args[3], (boolean) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "showOptionDialog":
|
||||
reply = gui.showOptionDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String[]) args[3], (int) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "showCardOptionDialog":
|
||||
reply = gui.showCardOptionDialog((CardView) args[0], (String) args[1], (String) args[2], (FSkinProp) args[3], (String[]) args[4], (int) args[5]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "showInputDialog":
|
||||
reply = gui.showInputDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String) args[3], (String[]) args[4]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "confirm":
|
||||
reply = gui.confirm((CardView) args[0], (String) args[1], (boolean) args[2], (String[]) args[3]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "getChoices":
|
||||
reply = (Serializable) gui.getChoices((String) args[0], (int) args[1], (int) args[2], (Collection<Object>) args[3], args[4], (Function<Object, String>) args[5]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "order":
|
||||
reply = (Serializable) gui.order((String) args[0], (String) args[1], (int) args[2], (int) args[3], (List<Object>) args[4], (List<Object>) args[5], (CardView) args[6], (boolean) args[7]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "sideboard":
|
||||
reply = (Serializable) gui.sideboard((CardPool) args[0], (CardPool) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "chooseSingleEntityForEffect":
|
||||
reply = gui.chooseSingleEntityForEffect((String) args[0], (TrackableCollection<GameEntityView>) args[1], (DelayedReveal) args[2], (boolean) args[3]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "setCard":
|
||||
gui.setCard((CardView) args[0]);
|
||||
break;
|
||||
// TODO case "setPlayerAvatar":
|
||||
case "openZones":
|
||||
reply = gui.openZones((Collection<ZoneType>) args[0], (Map<PlayerView, Object>) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
case "restoreOldZones":
|
||||
gui.restoreOldZones((Map<PlayerView, Object>) args[0]);
|
||||
break;
|
||||
case "isUiSetToSkipPhase":
|
||||
reply = gui.isUiSetToSkipPhase((PlayerView) args[0], (PhaseType) args[1]);
|
||||
doReply = true;
|
||||
break;
|
||||
// BUTTONS
|
||||
case "btn_setEnabled":
|
||||
btn.setEnabled((boolean) args[2]);
|
||||
break;
|
||||
case "btn_setVisible":
|
||||
btn.setVisible((boolean) args[2]);
|
||||
break;
|
||||
case "btn_setText":
|
||||
btn.setText((String) args[2]);
|
||||
break;
|
||||
case "btn_isSelected":
|
||||
reply = btn.isSelected();
|
||||
doReply = true;
|
||||
break;
|
||||
case "btn_setSelected":
|
||||
btn.setSelected((boolean) args[2]);
|
||||
break;
|
||||
case "btn_requestFocusInWindows":
|
||||
reply = btn.requestFocusInWindow();
|
||||
doReply = true;
|
||||
break;
|
||||
case "btn_setCommand":
|
||||
btn.setCommand((UiCommand) args[2]);
|
||||
break;
|
||||
case "btn_setTextColor":
|
||||
if (args.length == 3) {
|
||||
btn.setTextColor((FSkinProp) args[2]);
|
||||
} else {
|
||||
btn.setTextColor((int) args[2], (int) args[3], (int) args[4]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.err.println("Unsupported game event " + event.getMethod());
|
||||
break;
|
||||
}
|
||||
if (doReply) {
|
||||
client.send(new ReplyEvent(event.getId(), reply));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
|
||||
cause.printStackTrace();
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
6
forge-gui/src/main/java/forge/net/client/IToServer.java
Normal file
6
forge-gui/src/main/java/forge/net/client/IToServer.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package forge.net.client;
|
||||
|
||||
import forge.net.IRemote;
|
||||
|
||||
public interface IToServer extends IRemote {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge.net;
|
||||
package forge.net.client;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
@@ -9,8 +9,7 @@ import forge.game.spellability.SpellAbilityView;
|
||||
import forge.interfaces.IDevModeCheats;
|
||||
import forge.interfaces.IGameController;
|
||||
import forge.match.NextGameDecision;
|
||||
import forge.net.game.GuiGameEvent;
|
||||
import forge.net.game.client.IToServer;
|
||||
import forge.net.event.GuiGameEvent;
|
||||
import forge.util.ITriggerEvent;
|
||||
|
||||
public class NetGameController implements IGameController {
|
||||
@@ -0,0 +1 @@
|
||||
package forge.net.client;
|
||||
31
forge-gui/src/main/java/forge/net/event/ReplyEvent.java
Normal file
31
forge-gui/src/main/java/forge/net/event/ReplyEvent.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package forge.net.event;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import forge.net.server.RemoteClient;
|
||||
|
||||
public final class ReplyEvent implements NetEvent {
|
||||
private static final long serialVersionUID = -2814651319617795386L;
|
||||
|
||||
private final int index;
|
||||
private final Serializable reply;
|
||||
public ReplyEvent(final int index, final Serializable reply) {
|
||||
this.index = index;
|
||||
this.reply = reply;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
public Object getReply() {
|
||||
return reply;
|
||||
}
|
||||
|
||||
@Override public void updateForClient(final RemoteClient client) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("Reply (%d): %s", index, reply);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package forge.net.event;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import forge.AIOption;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.match.LobbySlotType;
|
||||
import forge.net.server.RemoteClient;
|
||||
|
||||
public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||
private static final long serialVersionUID = -5073305607515425968L;
|
||||
|
||||
private final LobbySlotType type;
|
||||
private final String name;
|
||||
private final int avatarIndex;
|
||||
private final int team;
|
||||
private final Boolean isArchenemy;
|
||||
private final Boolean isReady;
|
||||
private final Deck deck;
|
||||
private final DeckSection section;
|
||||
private final CardPool cards;
|
||||
private final Set<AIOption> aiOptions;
|
||||
|
||||
public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set<AIOption> aiOptions) {
|
||||
return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, null, null, null, aiOptions);
|
||||
}
|
||||
public static UpdateLobbyPlayerEvent deckUpdate(final Deck deck) {
|
||||
return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, deck, null, null, null);
|
||||
}
|
||||
public static UpdateLobbyPlayerEvent deckUpdate(final DeckSection section, final CardPool cards) {
|
||||
return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, null, section, cards, null);
|
||||
}
|
||||
|
||||
private UpdateLobbyPlayerEvent(final LobbySlotType type, final String name, final int avatarIndex, final int team, final Boolean isArchenemy, final Boolean isReady, final Deck deck, final DeckSection section, final CardPool cards, final Set<AIOption> aiOptions) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.avatarIndex = avatarIndex;
|
||||
this.team = team;
|
||||
this.isArchenemy = isArchenemy;
|
||||
this.isReady = isReady;
|
||||
this.deck = deck;
|
||||
this.section = section;
|
||||
this.cards = cards;
|
||||
this.aiOptions = aiOptions;
|
||||
}
|
||||
|
||||
public void updateForClient(final RemoteClient client) {
|
||||
}
|
||||
|
||||
public LobbySlotType getType() {
|
||||
return type;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
public int getTeam() {
|
||||
return team;
|
||||
}
|
||||
public Boolean getArchenemy() {
|
||||
return isArchenemy;
|
||||
}
|
||||
public Boolean getReady() {
|
||||
return isReady;
|
||||
}
|
||||
public Deck getDeck() {
|
||||
return deck;
|
||||
}
|
||||
public DeckSection getSection() {
|
||||
return section;
|
||||
}
|
||||
public CardPool getCards() {
|
||||
return cards;
|
||||
}
|
||||
public Set<AIOption> getAiOptions() {
|
||||
return aiOptions == null ? null : Collections.unmodifiableSet(aiOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package forge.net.event;
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge.net;
|
||||
package forge.net.server;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.GuiBase;
|
||||
@@ -11,16 +11,16 @@ import forge.interfaces.IGameController;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.interfaces.ILobbyListener;
|
||||
import forge.match.LobbySlot;
|
||||
import forge.match.LobbySlotType;
|
||||
import forge.match.NextGameDecision;
|
||||
import forge.net.game.GuiGameEvent;
|
||||
import forge.net.game.LobbySlotType;
|
||||
import forge.net.game.LoginEvent;
|
||||
import forge.net.game.LogoutEvent;
|
||||
import forge.net.game.MessageEvent;
|
||||
import forge.net.game.NetEvent;
|
||||
import forge.net.game.ReplyEvent;
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.net.game.server.RemoteClient;
|
||||
import forge.net.event.GuiGameEvent;
|
||||
import forge.net.event.LobbyUpdateEvent;
|
||||
import forge.net.event.LoginEvent;
|
||||
import forge.net.event.LogoutEvent;
|
||||
import forge.net.event.MessageEvent;
|
||||
import forge.net.event.NetEvent;
|
||||
import forge.net.event.ReplyEvent;
|
||||
import forge.net.event.UpdateLobbyPlayerEvent;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.util.ITriggerEvent;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
@@ -41,7 +41,7 @@ import io.netty.handler.logging.LogLevel;
|
||||
import io.netty.handler.logging.LoggingHandler;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -205,7 +205,7 @@ public final class FServerManager {
|
||||
private void mapNatPort(final int port) {
|
||||
final String localAddress;
|
||||
try {
|
||||
localAddress = Inet4Address.getLocalHost().getHostAddress();
|
||||
localAddress = InetAddress.getLocalHost().getHostAddress();
|
||||
} catch (final UnknownHostException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -436,7 +436,7 @@ public final class FServerManager {
|
||||
if (msg instanceof LoginEvent) {
|
||||
final String username = ((LoginEvent) msg).getUsername();
|
||||
client.setUsername(username);
|
||||
broadcast(new MessageEvent(null, String.format("%s joined the room", username)));
|
||||
broadcast(new MessageEvent(String.format("%s joined the room", username)));
|
||||
updateLobbyState();
|
||||
} else if (msg instanceof UpdateLobbyPlayerEvent) {
|
||||
localLobby.applyToSlot(client.getIndex(), (UpdateLobbyPlayerEvent) msg);
|
||||
6
forge-gui/src/main/java/forge/net/server/IToClient.java
Normal file
6
forge-gui/src/main/java/forge/net/server/IToClient.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package forge.net.server;
|
||||
|
||||
import forge.net.IRemote;
|
||||
|
||||
public interface IToClient extends IRemote {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge.net;
|
||||
package forge.net.server;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.EnumMap;
|
||||
@@ -26,8 +26,7 @@ import forge.interfaces.IButton;
|
||||
import forge.item.PaperCard;
|
||||
import forge.match.AbstractGuiGame;
|
||||
import forge.match.MatchButtonType;
|
||||
import forge.net.game.GuiGameEvent;
|
||||
import forge.net.game.server.IToClient;
|
||||
import forge.net.event.GuiGameEvent;
|
||||
import forge.player.PlayerZoneUpdate;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.util.ITriggerEvent;
|
||||
52
forge-gui/src/main/java/forge/net/server/RemoteClient.java
Normal file
52
forge-gui/src/main/java/forge/net/server/RemoteClient.java
Normal file
@@ -0,0 +1,52 @@
|
||||
package forge.net.server;
|
||||
|
||||
import forge.net.ReplyPool;
|
||||
import forge.net.event.IdentifiableNetEvent;
|
||||
import forge.net.event.NetEvent;
|
||||
import io.netty.channel.Channel;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public final class RemoteClient implements IToClient {
|
||||
|
||||
private final Channel channel;
|
||||
private String username;
|
||||
private int index;
|
||||
private ReplyPool replies = new ReplyPool();
|
||||
public RemoteClient(final Channel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final NetEvent event) {
|
||||
System.out.println("Sending event " + event + " to " + channel);
|
||||
channel.writeAndFlush(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException {
|
||||
replies.initialize(event.getId());
|
||||
|
||||
send(event);
|
||||
|
||||
return replies.get(event.getId());
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
public void setUsername(final String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
public void setIndex(final int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public void setReply(final int id, final Object reply) {
|
||||
replies.complete(id, reply);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package forge.net;
|
||||
package forge.net.server;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -8,7 +8,7 @@ import forge.AIOption;
|
||||
import forge.interfaces.IGuiGame;
|
||||
import forge.match.GameLobby;
|
||||
import forge.match.LobbySlot;
|
||||
import forge.net.game.LobbySlotType;
|
||||
import forge.match.LobbySlotType;
|
||||
|
||||
public final class ServerGameLobby extends GameLobby {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package forge.net.server;
|
||||
Reference in New Issue
Block a user