From ad7dc669e29822cda6addc39c65928faaa601828 Mon Sep 17 00:00:00 2001 From: Sten Laane <21343173+StenAL@users.noreply.github.com> Date: Mon, 3 Jun 2024 06:16:49 +0300 Subject: [PATCH] Server: Upgrade Netty to version 4.1 The final release of the Netty 3.x line was in 2016 and ever since, it has been EOL (https://netty.io/news/2016/06/29/3-10-6-Final.html). Nowadays it has multiple unpatched security issues. This patch migrates the server to the latest Netty release. 4.1.112. The 4.0 branch is skipped since it is also EOL since 2018. There are a bunch of breaking changes between the versions: - Channel attachments were removed in favor of attributes, so now ClientState and Player objects are stored as attributes - `flush` needs to be called to actually send messages to clients so all calls to `write` are replaced with `writeAndFlush`. In theory this can be optimized to buffer multiple writes but since the server is not performance critical, I opted to keep it simple and always flush writes. - All Netty imports had their package changed from org.jboss to io.netty - ChannelBuffer was renamed to ByteBuf - A bunch of handler methods were renamed (e.g. channelConnected -> channelActive, messageReceived -> channelRead, channelClosed -> channelInactive) - IdleStateAwareChannelHandler was removed and now idle events are be processed by `userEventTriggered`. `getLastActivityTimeMillis` was also removed from idle events, so I reimplemented that functionality in ClientState. - OneToOneDecoder and OneToOneEncoder were replaced with more strongly typed classes, ByteToMessageDecoder and MessageToByteEncoder. They no longer return values, instead they add to the output list passed in as a parameter. - The ServerBootstrap API was redesigned to use a fluent API and a ChannelInitializer instead of a pipeline factory. The new API is mostly compatible with the old one though. --- pom.xml | 4 +- server/pom.xml | 2 +- .../java/org/moparforia/server/Server.java | 70 +++++++++++-------- .../server/event/ClientConnectedEvent.java | 5 +- .../server/event/ClientDisconnectedEvent.java | 6 +- .../java/org/moparforia/server/game/Game.java | 6 +- .../org/moparforia/server/game/Lobby.java | 14 ++-- .../org/moparforia/server/game/Player.java | 4 +- .../server/game/PlayerCollection.java | 8 +-- .../server/game/gametypes/GolfGame.java | 6 +- .../server/game/gametypes/golf/DualGame.java | 2 +- .../server/net/ClientChannelHandler.java | 56 ++++++++------- .../moparforia/server/net/ClientState.java | 50 +++++++++---- .../org/moparforia/server/net/Packet.java | 2 +- .../moparforia/server/net/PacketDecoder.java | 37 +++++----- .../moparforia/server/net/PacketEncoder.java | 38 +++++----- .../server/net/packethandlers/NewHandler.java | 6 +- .../net/packethandlers/QuitHandler.java | 2 +- .../net/packethandlers/ReconnectHandler.java | 6 +- .../net/packethandlers/VersionHandler.java | 4 +- .../net/packethandlers/golf/ChatHandler.java | 8 +-- .../net/packethandlers/golf/GameHandler.java | 2 +- .../packethandlers/golf/LanguageHandler.java | 2 +- .../golf/LobbyCreateSinglePlayerHandler.java | 2 +- .../golf/LobbyDualplayerHandler.java | 14 ++-- .../net/packethandlers/golf/LobbyHandler.java | 4 +- .../golf/LobbyMultiplayerHandler.java | 2 +- .../golf/LobbySelectHandler.java | 4 +- .../net/packethandlers/golf/LoginHandler.java | 6 +- .../packethandlers/golf/LoginTypeHandler.java | 2 +- .../golf/TrackTestLoginHandler.java | 6 +- 31 files changed, 209 insertions(+), 171 deletions(-) diff --git a/pom.xml b/pom.xml index 63d497e7..2e0a4fb3 100644 --- a/pom.xml +++ b/pom.xml @@ -96,8 +96,8 @@ io.netty - netty - 3.10.6.Final + netty-all + 4.1.112.Final compile diff --git a/server/pom.xml b/server/pom.xml index c8678bbd..dd0fa844 100644 --- a/server/pom.xml +++ b/server/pom.xml @@ -19,7 +19,7 @@ io.netty - netty + netty-all compile diff --git a/server/src/main/java/org/moparforia/server/Server.java b/server/src/main/java/org/moparforia/server/Server.java index 1fe8a4f7..1b51c406 100644 --- a/server/src/main/java/org/moparforia/server/Server.java +++ b/server/src/main/java/org/moparforia/server/Server.java @@ -1,14 +1,20 @@ package org.moparforia.server; -import org.jboss.netty.bootstrap.ServerBootstrap; -import org.jboss.netty.channel.*; -import org.jboss.netty.channel.group.ChannelGroup; -import org.jboss.netty.channel.group.DefaultChannelGroup; -import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; -import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder; -import org.jboss.netty.handler.codec.frame.Delimiters; -import org.jboss.netty.handler.timeout.IdleStateHandler; -import org.jboss.netty.util.HashedWheelTimer; +import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.group.ChannelGroup; +import io.netty.channel.group.DefaultChannelGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.codec.DelimiterBasedFrameDecoder; +import io.netty.handler.codec.Delimiters; +import io.netty.handler.timeout.IdleStateHandler; +import io.netty.util.concurrent.GlobalEventExecutor; import org.moparforia.server.event.Event; import org.moparforia.server.game.Lobby; import org.moparforia.server.game.LobbyType; @@ -32,8 +38,6 @@ import java.util.Iterator; import java.util.Optional; import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; public class Server implements Runnable { @@ -42,7 +46,7 @@ public class Server implements Runnable { public static final String DEFAULT_TRACKS_DIRECTORY = "tracks"; private HashMap players = new HashMap<>(); - private ChannelGroup allChannels = new DefaultChannelGroup(); + private ChannelGroup allChannels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); private ConcurrentLinkedQueue events = new ConcurrentLinkedQueue<>(); private HashMap> packetHandlers = new HashMap<>(); @@ -50,7 +54,7 @@ public class Server implements Runnable { private int port; private Optional tracksDirectory; - private Channel serverChannel; + private ChannelFuture serverChannelFuture; private boolean running; private HashMap lobbies = new HashMap(); @@ -175,23 +179,29 @@ public void start() { packetHandlers = PacketHandlerFactory.getPacketHandlers(); System.out.println("Loaded " + packetHandlers.size() + " packet handler type(s)"); - ChannelFactory factory = new NioServerSocketChannelFactory( - Executors.newCachedThreadPool(), - Executors.newCachedThreadPool()); - - ServerBootstrap bootstrap = new ServerBootstrap(factory); - final ClientChannelHandler clientHandler = new ClientChannelHandler(this); - final IdleStateHandler idleState = new IdleStateHandler(new HashedWheelTimer(1, TimeUnit.SECONDS), 2, 0, 0); - bootstrap.setPipelineFactory(() -> Channels.pipeline( - new DelimiterBasedFrameDecoder(250, Delimiters.lineDelimiter()), - new PacketDecoder(), - new PacketEncoder(), - idleState, - clientHandler)); - bootstrap.setOption("child.tcpNoDelay", true); - bootstrap.setOption("child.keepAlive", true); + EventLoopGroup bossGroup = new NioEventLoopGroup(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); + ServerBootstrap bootstrap = new ServerBootstrap() + .group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .childHandler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) { + ch.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).set(new ClientState()); + ch.pipeline() + .addLast( + new DelimiterBasedFrameDecoder(250, Delimiters.lineDelimiter()), + new PacketDecoder(), + new PacketEncoder(), + new IdleStateHandler(2, 0, 0), + new ClientChannelHandler(Server.this) + ); + } + }) + .childOption(ChannelOption.TCP_NODELAY, true) + .childOption(ChannelOption.SO_KEEPALIVE, true); try { - this.serverChannel = bootstrap.bind(new InetSocketAddress(host, port)); + this.serverChannelFuture = bootstrap.bind(new InetSocketAddress(host, port)).sync(); this.running = true; new Thread(this).start(); } catch (Exception ex) { @@ -200,7 +210,7 @@ public void start() { } public void stop() throws InterruptedException { - this.serverChannel.close().sync(); + this.serverChannelFuture.channel().close().sync(); this.running = false; } diff --git a/server/src/main/java/org/moparforia/server/event/ClientConnectedEvent.java b/server/src/main/java/org/moparforia/server/event/ClientConnectedEvent.java index b61cbdfc..9bd63476 100644 --- a/server/src/main/java/org/moparforia/server/event/ClientConnectedEvent.java +++ b/server/src/main/java/org/moparforia/server/event/ClientConnectedEvent.java @@ -1,6 +1,6 @@ package org.moparforia.server.event; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; import org.moparforia.server.Server; import java.util.Random; @@ -17,8 +17,7 @@ public ClientConnectedEvent(Channel channel) { public void process(Server server) { System.out.println("Client connected: " + channel); server.addChannel(channel); - //channel.write("h 1\nc io " + new Random().nextInt(1000000000) + "\nc crt 25\nc ctr\n"); - channel.write("h 1\nc io " + new Random().nextInt(1000000000) + "\nc crt 250\nc ctr\n"); + channel.writeAndFlush("h 1\nc io " + new Random().nextInt(1000000000) + "\nc crt 250\nc ctr\n"); } } diff --git a/server/src/main/java/org/moparforia/server/event/ClientDisconnectedEvent.java b/server/src/main/java/org/moparforia/server/event/ClientDisconnectedEvent.java index 6c24f985..69307ae5 100644 --- a/server/src/main/java/org/moparforia/server/event/ClientDisconnectedEvent.java +++ b/server/src/main/java/org/moparforia/server/event/ClientDisconnectedEvent.java @@ -1,6 +1,6 @@ package org.moparforia.server.event; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; import org.moparforia.server.Server; import org.moparforia.server.game.Lobby; import org.moparforia.server.game.Player; @@ -15,8 +15,8 @@ public ClientDisconnectedEvent(Channel channel) { @Override public void process(Server server) { - Player player; - if ((player = (Player)channel.getAttachment()) != null) { + Player player = channel.attr(Player.PLAYER_ATTRIBUTE_KEY).get(); + if (player != null) { if (player.getLobby() != null) { player.getLobby().removePlayer(player, Lobby.PART_REASON_USERLEFT); } diff --git a/server/src/main/java/org/moparforia/server/game/Game.java b/server/src/main/java/org/moparforia/server/game/Game.java index 796a90b3..2715a9ae 100644 --- a/server/src/main/java/org/moparforia/server/game/Game.java +++ b/server/src/main/java/org/moparforia/server/game/Game.java @@ -1,6 +1,6 @@ package org.moparforia.server.game; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; import org.moparforia.server.Server; import org.moparforia.server.game.gametypes.golf.MultiGame; import org.moparforia.server.net.Packet; @@ -102,7 +102,7 @@ protected void sendJoinMessages(Player player) { sendGameInfo(player); sendPlayerNames(player); writeExcluding(player, new Packet(PacketType.DATA, Tools.tabularize("game", "join", playerCount(), player.getNick(), player.getClan()))); - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("game", "owninfo", numberIndex, player.getNick(), player.getClan()))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("game", "owninfo", numberIndex, player.getNick(), player.getClan()))); } protected void sendPlayerNames(Player player) { @@ -112,7 +112,7 @@ protected void sendPlayerNames(Player player) { if (!p.equals(player)) playersData += Tools.tabularize("", getPlayerId(p), p.getNick(), p.getClan()); } - c.write(new Packet(PacketType.DATA, playersData)); + c.writeAndFlush(new Packet(PacketType.DATA, playersData)); } diff --git a/server/src/main/java/org/moparforia/server/game/Lobby.java b/server/src/main/java/org/moparforia/server/game/Lobby.java index deefac12..de3719e3 100644 --- a/server/src/main/java/org/moparforia/server/game/Lobby.java +++ b/server/src/main/java/org/moparforia/server/game/Lobby.java @@ -45,7 +45,7 @@ public boolean removePlayer(Player player, int partReason, String... gameName) { writeAll(new Packet(PacketType.DATA, cmd)); if (player.getChannel().isWritable() && partReason == PART_REASON_USERLEFT) { - player.getChannel().write(new Packet(PacketType.DATA, "status\tlobbyselect\t300")); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, "status\tlobbyselect\t300")); } return true; } @@ -54,23 +54,23 @@ public boolean addPlayer(Player player, int joinType) { if (player.getLobby() != null) { player.getLobby().removePlayer(player, PART_REASON_USERLEFT); } - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("status", "lobby", type + (player.isChatHidden() ? "h" : "")))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("status", "lobby", type + (player.isChatHidden() ? "h" : "")))); String[] otherPlayers = new String[playerCount()]; int pointer = 0; for (Player p : getPlayers()) { - p.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize( + p.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize( "lobby", joinType == JOIN_TYPE_NORMAL ? "join" : "joinfromgame", player.toString()//todo not sure if should be getNick or getGameString ))); otherPlayers[pointer++] = p.toString(); } if (pointer != 0) { - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("lobby", "users", otherPlayers))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "users", otherPlayers))); } else { - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("lobby", "users"))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "users"))); } - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("lobby", "ownjoin", player.toString()))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "ownjoin", player.toString()))); if (getLobbyType() == LobbyType.MULTI) { sendGameList(player); } @@ -89,7 +89,7 @@ public void sendGameList(Player player) { length++; } } - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("lobby", "gamelist", "full", length, buff.toString()))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "gamelist", "full", length, buff.toString()))); } public Game getGame(int id) { diff --git a/server/src/main/java/org/moparforia/server/game/Player.java b/server/src/main/java/org/moparforia/server/game/Player.java index eb8708af..9068ce5e 100644 --- a/server/src/main/java/org/moparforia/server/game/Player.java +++ b/server/src/main/java/org/moparforia/server/game/Player.java @@ -1,10 +1,12 @@ package org.moparforia.server.game; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; +import io.netty.util.AttributeKey; import org.moparforia.shared.Tools; public class Player { + public static final AttributeKey PLAYER_ATTRIBUTE_KEY = AttributeKey.newInstance("PLAYER_ATTRIBUTE"); public static final int ACCESSLEVEL_NORMAL = 0; // todo: enum this ? public static final int ACCESSLEVEL_SHERIFF = 1; public static final int ACCESSLEVEL_ADMIN = 2; diff --git a/server/src/main/java/org/moparforia/server/game/PlayerCollection.java b/server/src/main/java/org/moparforia/server/game/PlayerCollection.java index 6f463d4e..ef61b462 100644 --- a/server/src/main/java/org/moparforia/server/game/PlayerCollection.java +++ b/server/src/main/java/org/moparforia/server/game/PlayerCollection.java @@ -34,20 +34,20 @@ protected boolean removePlayer(Player player) { public void writeAll(Packet packet) { for (Player player : getPlayers()) { - player.getChannel().write(packet); + player.getChannel().writeAndFlush(packet); } } public void writeAll(String message) { for (Player player : getPlayers()) { - player.getChannel().write(message); + player.getChannel().writeAndFlush(message); } } public void writeExcluding(Player exclude, Packet packet) { for (Player player : getPlayers()) { if (player != exclude) { - player.getChannel().write(packet); + player.getChannel().writeAndFlush(packet); } } } @@ -55,7 +55,7 @@ public void writeExcluding(Player exclude, Packet packet) { public void writeExcluding(Player exclude, String message) { for (Player player : getPlayers()) { if (player != exclude) { - player.getChannel().write(message); + player.getChannel().writeAndFlush(message); } } } diff --git a/server/src/main/java/org/moparforia/server/game/gametypes/GolfGame.java b/server/src/main/java/org/moparforia/server/game/gametypes/GolfGame.java index 546541bf..91ff7e04 100644 --- a/server/src/main/java/org/moparforia/server/game/gametypes/GolfGame.java +++ b/server/src/main/java/org/moparforia/server/game/gametypes/GolfGame.java @@ -1,6 +1,6 @@ package org.moparforia.server.game.gametypes; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; import org.moparforia.server.Server; import org.moparforia.server.game.Game; import org.moparforia.server.game.Lobby; @@ -137,8 +137,8 @@ public void rateTrack(String rating) { public void sendGameInfo(Player player) { Channel c = player.getChannel(); - c.write(new Packet(PacketType.DATA, Tools.tabularize("status", "game"))); - c.write(new Packet(PacketType.DATA, Tools.tabularize("game", "gameinfo", + c.writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("status", "game"))); + c.writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("game", "gameinfo", name, passworded ? "t" : "f", gameId, numPlayers, tracks.size(), tracksType, maxStrokes, strokeTimeout, waterEvent, collision, trackScoring, trackScoringEnd, "f"))); diff --git a/server/src/main/java/org/moparforia/server/game/gametypes/golf/DualGame.java b/server/src/main/java/org/moparforia/server/game/gametypes/golf/DualGame.java index e26d7dda..3f441154 100644 --- a/server/src/main/java/org/moparforia/server/game/gametypes/golf/DualGame.java +++ b/server/src/main/java/org/moparforia/server/game/gametypes/golf/DualGame.java @@ -26,7 +26,7 @@ public DualGame(Player challenger, Player challenged, int gameId, int numberOfTr false, numberOfTracks, -1, tracksType, maxStrokes, strokeTimeout, waterEvent, collision, trackScoring, trackScoringEnd, 2); - challenged.getChannel().write(new Packet(PacketType.DATA, + challenged.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "challenge", challenger.getNick(), numberOfTracks, tracksType, maxStrokes, strokeTimeout, waterEvent, collision, trackScoring, trackScoringEnd))); diff --git a/server/src/main/java/org/moparforia/server/net/ClientChannelHandler.java b/server/src/main/java/org/moparforia/server/net/ClientChannelHandler.java index e6ecba48..1e06f2d3 100644 --- a/server/src/main/java/org/moparforia/server/net/ClientChannelHandler.java +++ b/server/src/main/java/org/moparforia/server/net/ClientChannelHandler.java @@ -1,13 +1,15 @@ package org.moparforia.server.net; -import org.jboss.netty.channel.*; -import org.jboss.netty.handler.timeout.IdleState; -import org.jboss.netty.handler.timeout.IdleStateAwareChannelHandler; -import org.jboss.netty.handler.timeout.IdleStateEvent; +import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.timeout.IdleState; +import io.netty.handler.timeout.IdleStateEvent; import org.moparforia.server.Server; import org.moparforia.server.event.*; +import org.moparforia.server.game.Player; -public class ClientChannelHandler extends IdleStateAwareChannelHandler { +public class ClientChannelHandler extends ChannelDuplexHandler { private final Server server; @@ -16,42 +18,46 @@ public ClientChannelHandler(Server server) { } @Override - public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - Packet packet = (Packet) e.getMessage(); - System.out.println(">>> " + e.getMessage()); + public void channelRead(ChannelHandlerContext ctx, Object msg) { + Packet packet = (Packet) msg; + System.out.println("<<< " + packet); + ctx.channel().attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().setLastActivityTime(System.currentTimeMillis()); server.addEvent(new PacketReceivedEvent(packet)); } @Override - public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) throws Exception { - if (e.getState() == IdleState.READER_IDLE) { - long time = System.currentTimeMillis() - e.getLastActivityTimeMillis(); - if (time > 20000) { - e.getChannel().close(); - } else if (time > 5000) { - e.getChannel().write("c ping\n"); + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { + if (evt instanceof IdleStateEvent e) { + if (e.state() == IdleState.READER_IDLE) { + ClientState state = ctx.channel().attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get(); + long time = System.currentTimeMillis() - state.getLastActivityTime(); + if (time > 20000) { + ctx.channel().close(); + } else if (time > 5000) { + ctx.channel().writeAndFlush("c ping\n"); + } } } } @Override - public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { - //noinspection ThrowableResultOfMethodCallIgnored - e.getCause().printStackTrace(); - e.getChannel().close(); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.channel().close(); } @Override - public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { - server.addEvent(new ClientConnectedEvent(e.getChannel())); + public void channelActive(ChannelHandlerContext ctx) { + server.addEvent(new ClientConnectedEvent(ctx.channel())); } @Override - public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) { - Channel channel = e.getChannel(); + public void channelInactive(ChannelHandlerContext ctx) { + Channel channel = ctx.channel(); server.addEvent(new ClientDisconnectedEvent(channel)); - final int id = channel.getId(); - if (server.hasPlayer(id)) { + Player player = channel.attr(Player.PLAYER_ATTRIBUTE_KEY).get(); + if (player != null && server.hasPlayer(player.getId())) { + int id = player.getId(); server.addEvent(new TimedEvent(30_000) { // todo: confirm this time @Override public void process(Server server) { diff --git a/server/src/main/java/org/moparforia/server/net/ClientState.java b/server/src/main/java/org/moparforia/server/net/ClientState.java index 1a4ad218..863fe2b4 100644 --- a/server/src/main/java/org/moparforia/server/net/ClientState.java +++ b/server/src/main/java/org/moparforia/server/net/ClientState.java @@ -1,22 +1,44 @@ package org.moparforia.server.net; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelLocal; + +import io.netty.util.AttributeKey; + public final class ClientState { - public static final ChannelLocal sentCount = new ChannelLocal() { - @Override - protected Long initialValue(Channel channel) { - return 0L; - } - }; + public static final AttributeKey CLIENT_STATE_ATTRIBUTE_KEY = AttributeKey.valueOf("MESSAGE_COUNTS"); + + private long sentCount; + private long receivedCount; + private long lastActivityTime; + + public ClientState() { + this.sentCount = 0; + this.receivedCount = 0; + this.lastActivityTime = System.currentTimeMillis(); + } + + public long getSentCount() { + return sentCount; + } + + public void setSentCount(long sentCount) { + this.sentCount = sentCount; + } + + public long getReceivedCount() { + return receivedCount; + } + + public void setReceivedCount(long receivedCount) { + this.receivedCount = receivedCount; + } - public static final ChannelLocal recvCount = new ChannelLocal() { - @Override - protected Long initialValue(Channel channel) { - return 0L; - } - }; + public long getLastActivityTime() { + return lastActivityTime; + } + public void setLastActivityTime(long lastActivityTime) { + this.lastActivityTime = lastActivityTime; + } } diff --git a/server/src/main/java/org/moparforia/server/net/Packet.java b/server/src/main/java/org/moparforia/server/net/Packet.java index 371bc6c3..7cab2b38 100644 --- a/server/src/main/java/org/moparforia/server/net/Packet.java +++ b/server/src/main/java/org/moparforia/server/net/Packet.java @@ -1,6 +1,6 @@ package org.moparforia.server.net; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; @SuppressWarnings("SameParameterValue") public class Packet { diff --git a/server/src/main/java/org/moparforia/server/net/PacketDecoder.java b/server/src/main/java/org/moparforia/server/net/PacketDecoder.java index f2b99a95..bf1438ed 100644 --- a/server/src/main/java/org/moparforia/server/net/PacketDecoder.java +++ b/server/src/main/java/org/moparforia/server/net/PacketDecoder.java @@ -1,27 +1,26 @@ package org.moparforia.server.net; -import org.jboss.netty.buffer.ChannelBuffer; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.oneone.OneToOneDecoder; -import org.jboss.netty.util.CharsetUtil; +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; +import io.netty.util.CharsetUtil; -public class PacketDecoder extends OneToOneDecoder { +import java.util.List; + +public class PacketDecoder extends ByteToMessageDecoder { @Override - protected Object decode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { - if (msg instanceof ChannelBuffer) { - Packet packet = new Packet(channel, ((ChannelBuffer) msg).toString(CharsetUtil.UTF_8)); - if (packet.getType() == PacketType.DATA) { - long count = ClientState.recvCount.get(channel); - if (count == packet.getCount()) { - ClientState.recvCount.set(channel, count + 1); - } else { - channel.close(); - return null; - } + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + Channel channel = ctx.channel(); + Packet packet = new Packet(channel, in.readBytes(in.readableBytes()).toString(CharsetUtil.UTF_8)); + if (packet.getType() == PacketType.DATA) { + long count = channel.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().getReceivedCount(); + if (count == packet.getCount()) { + channel.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().setReceivedCount(count + 1); + } else { + channel.close(); } - return packet; } - return msg; + out.add(packet); } } diff --git a/server/src/main/java/org/moparforia/server/net/PacketEncoder.java b/server/src/main/java/org/moparforia/server/net/PacketEncoder.java index c0e5bc7f..c1e9a5c3 100644 --- a/server/src/main/java/org/moparforia/server/net/PacketEncoder.java +++ b/server/src/main/java/org/moparforia/server/net/PacketEncoder.java @@ -1,44 +1,44 @@ package org.moparforia.server.net; -import org.jboss.netty.channel.Channel; -import org.jboss.netty.channel.ChannelHandlerContext; -import org.jboss.netty.handler.codec.oneone.OneToOneEncoder; -import org.jboss.netty.util.CharsetUtil; +import io.netty.buffer.ByteBuf; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; +import io.netty.util.CharsetUtil; -import static org.jboss.netty.buffer.ChannelBuffers.copiedBuffer; +import static io.netty.buffer.Unpooled.copiedBuffer; -public class PacketEncoder extends OneToOneEncoder { +public class PacketEncoder extends MessageToByteEncoder { @Override - protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception { - if (msg instanceof Packet) { - Packet packet = (Packet) msg; + protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) { + Channel channel = ctx.channel(); + if (msg instanceof Packet packet) { String encoded; if (packet.getType() != PacketType.NONE) { encoded = packet.getType().toString().toLowerCase().charAt(0) + " "; if (packet.getType() == PacketType.DATA) { - long count = ClientState.sentCount.get(channel); + long count = channel.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().getSentCount(); encoded += count + " "; - ClientState.sentCount.set(channel, count + 1); + channel.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().setSentCount(count + 1); } } else { encoded = ""; } encoded += packet.getMessage() + '\n'; - return copiedBuffer(ctx.getChannel().getConfig().getBufferFactory().getDefaultOrder(), encoded, CharsetUtil.UTF_8); - } else if (msg instanceof String) { - String m = (String) msg; + out.writeBytes(copiedBuffer(encoded, CharsetUtil.UTF_8)); + } else if (msg instanceof String m) { if (!m.endsWith("\n")) { m += "\n"; } if (m.startsWith("d ")) { - long count = ClientState.sentCount.get(channel); + long count = channel.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().getSentCount(); m = "d " + count + " " + m.substring(2); - ClientState.sentCount.set(channel, count + 1); + channel.attr(ClientState.CLIENT_STATE_ATTRIBUTE_KEY).get().setSentCount(count + 1); } - return copiedBuffer(ctx.getChannel().getConfig().getBufferFactory().getDefaultOrder(), m, CharsetUtil.UTF_8); + out.writeBytes(copiedBuffer(m, CharsetUtil.UTF_8)); + } else { + out.writeBytes((ByteBuf) msg); } - return msg; } - } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/NewHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/NewHandler.java index 401e645d..f63ffb0c 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/NewHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/NewHandler.java @@ -1,6 +1,6 @@ package org.moparforia.server.net.packethandlers; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; import org.moparforia.server.Server; import org.moparforia.server.event.PlayerConnectedEvent; import org.moparforia.server.game.Player; @@ -28,9 +28,9 @@ public boolean handle(Server server, Packet packet, Matcher message) { Channel channel = packet.getChannel(); int id = server.getNextPlayerId(); Player player = new Player(channel, id); - channel.setAttachment(player); + channel.attr(Player.PLAYER_ATTRIBUTE_KEY).set(player); server.addPlayer(player); - channel.write("c id " + id + "\n"); + channel.writeAndFlush("c id " + id + "\n"); server.addEvent(new PlayerConnectedEvent(player.getId(), false)); return true; } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/QuitHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/QuitHandler.java index 454bfa90..2b85ec81 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/QuitHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/QuitHandler.java @@ -26,7 +26,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); if (message.group(1).contains("lobby")) { player.getLobby().removePlayer(player, Lobby.PART_REASON_USERLEFT); } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/ReconnectHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/ReconnectHandler.java index 185ce45a..8524f767 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/ReconnectHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/ReconnectHandler.java @@ -1,6 +1,6 @@ package org.moparforia.server.net.packethandlers; -import org.jboss.netty.channel.Channel; +import io.netty.channel.Channel; import org.moparforia.server.Server; import org.moparforia.server.event.PlayerConnectedEvent; import org.moparforia.server.game.Player; @@ -32,8 +32,8 @@ public boolean handle(Server server, Packet packet, Matcher message) { Player p = server.getPlayer(id); Channel c = packet.getChannel(); p.setChannel(c); - c.setAttachment(p); - c.write("c rcok\n"); + c.attr(Player.PLAYER_ATTRIBUTE_KEY).set(p); + c.writeAndFlush("c rcok\n"); server.addEvent(new PlayerConnectedEvent(id, true)); } return true; diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/VersionHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/VersionHandler.java index cd768d27..854befac 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/VersionHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/VersionHandler.java @@ -30,10 +30,10 @@ public boolean handle(Server server, Packet packet, Matcher message) { packet.getChannel().close(); return true; } - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); player.setGameType(gameType); if(gameType == GameType.GOLF) { - player.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("status", "login"))); + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("status", "login"))); }//todo return true; } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/ChatHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/ChatHandler.java index 9a7d559c..f79ab5de 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/ChatHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/ChatHandler.java @@ -29,7 +29,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); PlayerCollection destination; if (message.group(1).equals("game")) { destination = player.getGame(); @@ -43,10 +43,10 @@ public boolean handle(Server server, Packet packet, Matcher message) { for (Player otherPlayer : destination.getPlayers()) { if (player != otherPlayer) { if (message.group(1).equals("game")) { - otherPlayer.getChannel().write(new Packet(PacketType.DATA, + otherPlayer.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("game", "say", ((Game) destination).getPlayerId(player), message.group(3)))); } else { - otherPlayer.getChannel().write(new Packet(PacketType.DATA, + otherPlayer.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "say", message.group(3), player.getNick(), message.group(4)))); } } @@ -54,7 +54,7 @@ public boolean handle(Server server, Packet packet, Matcher message) { } else if (message.group(2).equals("sayp")) { for (Player otherPlayer : destination.getPlayers()) { if (otherPlayer.getNick().equals(message.group(3))) { - otherPlayer.getChannel().write(new Packet(PacketType.DATA, + otherPlayer.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize(message.group(1), "sayp", player.getNick(), message.group(4)))); break; } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/GameHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/GameHandler.java index 208b9acd..dbbc4d13 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/GameHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/GameHandler.java @@ -28,7 +28,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); Game game = player.getGame(); return game.handlePacket(server, player, message); } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LanguageHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LanguageHandler.java index 89eda1ff..d3ab0d28 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LanguageHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LanguageHandler.java @@ -23,7 +23,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); player.setLocale(message.group(1)); // todo: check if we axly support this locale return true; } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyCreateSinglePlayerHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyCreateSinglePlayerHandler.java index 9ed11b42..23afc780 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyCreateSinglePlayerHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyCreateSinglePlayerHandler.java @@ -28,7 +28,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); int number = Integer.parseInt(message.group(2)); if (message.group(1).equals("t")) { int trackType = Integer.parseInt(message.group(3)); diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyDualplayerHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyDualplayerHandler.java index 3a6b0768..e2501305 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyDualplayerHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyDualplayerHandler.java @@ -29,12 +29,12 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); if (message.group(1).equals("lobby")) { if (message.group(2).equals("challenge")) { Player other = getPlayer(server, message.group(3)); if (other == null) {// || other.isNotAcceptingChallenges()) { - player.getChannel().write(new Packet(PacketType.DATA, + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "cfail", "nochall"))); return true; } @@ -51,7 +51,7 @@ public boolean handle(Server server, Packet packet, Matcher message) { } else if (message.group(2).equals("accept")) { Player other = getPlayer(server, message.group(3)); if (other == null || !(other.getGame() instanceof DualGame)) { - player.getChannel().write(new Packet(PacketType.DATA, + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "cfail", "nouser")));//todo kick the faggot return true; } @@ -60,20 +60,20 @@ public boolean handle(Server server, Packet packet, Matcher message) { } else if (message.group(2).equals("cancel")) { Player other = getPlayer(server, message.group(3)); if (other == null || !(other.getGame() instanceof DualGame)) { - player.getChannel().write(new Packet(PacketType.DATA, + player.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "cfail", "nouser")));//todo kick the faggot return true; } - other.getChannel().write(new Packet(PacketType.DATA, + other.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "cancel"))); } else if (message.group(2).equals("cfail") && message.group(4).equals("refuse")) { Player other = getPlayer(server, message.group(3)); if (other == null || !(other.getGame() instanceof DualGame)) { - player.getChannel().write(new Packet(PacketType.DATA,//todo kick the faggot + player.getChannel().writeAndFlush(new Packet(PacketType.DATA,//todo kick the faggot Tools.tabularize("lobby", "cfail", "nouser"))); return true; } - other.getChannel().write(new Packet(PacketType.DATA, + other.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "cfail", "refuse"))); //todo HOW TO REMOVE THE GAME FROM THE SERVER } else if (message.group(2).equals("nc")) { diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyHandler.java index 69368245..65db4f6d 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyHandler.java @@ -35,7 +35,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); if (message.group(1).equals("back")) { if (player.getLobby() == null) { packet.getChannel().close(); @@ -73,7 +73,7 @@ public boolean handle(Server server, Packet packet, Matcher message) { for (int i = 0; i < tracksInfo.length; i++) { cmd += Tools.tabularize(tracksInfo[i]) + (i == tracksInfo.length - 1 ? "" : '\t'); } - packet.getChannel().write(new Packet(PacketType.DATA, + packet.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("lobby", "tracksetlist", cmd))); } return true; diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyMultiplayerHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyMultiplayerHandler.java index c387b122..966c338a 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyMultiplayerHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbyMultiplayerHandler.java @@ -30,7 +30,7 @@ public Pattern getPattern() { } public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); Lobby lobby = player.getLobby(); if (message.group(1).equals("c")) { diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbySelectHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbySelectHandler.java index 0a0b5f73..5de96283 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbySelectHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LobbySelectHandler.java @@ -30,11 +30,11 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { if (message.group(1).equals("rnop")) { - packet.getChannel().write("d lobbyselect\tnop\t" + Tools.tabularize(server.getLobby(LobbyType.SINGLE).totalPlayerCount(), server.getLobby(LobbyType.DUAL).totalPlayerCount(), server.getLobby(LobbyType.MULTI).totalPlayerCount())); + packet.getChannel().writeAndFlush("d lobbyselect\tnop\t" + Tools.tabularize(server.getLobby(LobbyType.SINGLE).totalPlayerCount(), server.getLobby(LobbyType.DUAL).totalPlayerCount(), server.getLobby(LobbyType.MULTI).totalPlayerCount())); } else if (message.group(1).equals("select")) { // 1 for single, 1h for single hidden chat, 2 for dual, x for multi LobbyType lobbyType = LobbyType.getLobby(message.group(2)); - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); player.setChatHidden(message.group(3) != null && message.group(3).equals("h")); server.getLobby(lobbyType).addPlayer(player, Lobby.JOIN_TYPE_NORMAL); } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginHandler.java index d3614221..020a1f0f 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginHandler.java @@ -27,7 +27,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); String username = "~anonym-" + (int) (Math.random() * 10000); @@ -36,8 +36,8 @@ public boolean handle(Server server, Packet packet, Matcher message) { player.setEmailVerified(true); player.setRegistered(false); - packet.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("basicinfo", player.isEmailVerified(), player.getAccessLevel(), "t", "t"))); - packet.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("status", "lobbyselect", "300"))); + packet.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("basicinfo", player.isEmailVerified(), player.getAccessLevel(), "t", "t"))); + packet.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("status", "lobbyselect", "300"))); return true; } } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginTypeHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginTypeHandler.java index fda04a7a..5164e9b1 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginTypeHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/LoginTypeHandler.java @@ -26,7 +26,7 @@ public Pattern getPattern() { @Override public boolean handle(Server server, Packet packet, Matcher message) { - packet.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("status", "login"))); + packet.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("status", "login"))); return true; } } diff --git a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/TrackTestLoginHandler.java b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/TrackTestLoginHandler.java index 597b78f1..e076c743 100644 --- a/server/src/main/java/org/moparforia/server/net/packethandlers/golf/TrackTestLoginHandler.java +++ b/server/src/main/java/org/moparforia/server/net/packethandlers/golf/TrackTestLoginHandler.java @@ -50,12 +50,12 @@ public boolean handle(Server server, Packet packet, Matcher message) { } } - Player player = (Player) packet.getChannel().getAttachment(); + Player player = packet.getChannel().attr(Player.PLAYER_ATTRIBUTE_KEY).get(); player.setNick(username); player.setEmailVerified(true); player.setRegistered(!anonym); - packet.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("basicinfo", player.isEmailVerified(), player.getAccessLevel(), "t", "f"))); - packet.getChannel().write(new Packet(PacketType.DATA, Tools.tabularize("status", "lobbyselect", 300))); + packet.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("basicinfo", player.isEmailVerified(), player.getAccessLevel(), "t", "f"))); + packet.getChannel().writeAndFlush(new Packet(PacketType.DATA, Tools.tabularize("status", "lobbyselect", 300))); return true; } }