From b049352fe3a4d04c9b202daac7059d60fb037e06 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 9 May 2021 20:07:08 +0300 Subject: [PATCH] PlayerManager --- .../mc/protocol/NettyConnectionContext.java | 33 +++++++++++++++++++ .../java/mc/protocol/NetworkAttributes.java | 8 +++++ .../mc/protocol/PacketInboundHandler.java | 4 ++- .../mc/protocol/api/ConnectionContext.java | 26 +++++++++++++++ .../mc/protocol/io/codec/ProtocolDecoder.java | 6 ++++ server/src/main/java/mc/server/Main.java | 7 +++- .../main/java/mc/server/PacketHandler.java | 20 +++++++---- server/src/main/java/mc/server/Player.java | 20 +++++++++++ .../mc/server/di/PacketHandlerModule.java | 5 +-- .../main/java/mc/server/di/PlayersModule.java | 16 +++++++++ .../java/mc/server/di/ServerComponent.java | 4 ++- .../java/mc/server/service/PlayerManager.java | 29 ++++++++++++++++ server/src/main/resources/config-sample.yml | 2 +- 13 files changed, 167 insertions(+), 13 deletions(-) create mode 100644 server/src/main/java/mc/server/Player.java create mode 100644 server/src/main/java/mc/server/di/PlayersModule.java create mode 100644 server/src/main/java/mc/server/service/PlayerManager.java diff --git a/protocol/src/main/java/mc/protocol/NettyConnectionContext.java b/protocol/src/main/java/mc/protocol/NettyConnectionContext.java index 23fe235..6aa0258 100644 --- a/protocol/src/main/java/mc/protocol/NettyConnectionContext.java +++ b/protocol/src/main/java/mc/protocol/NettyConnectionContext.java @@ -2,12 +2,16 @@ package mc.protocol; import io.netty.channel.ChannelHandlerContext; import lombok.EqualsAndHashCode; +import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; import mc.protocol.api.ConnectionContext; import mc.protocol.packets.ServerSidePacket; import mc.protocol.pool.Passivable; +import java.util.Map; +import java.util.Optional; + @EqualsAndHashCode public class NettyConnectionContext implements ConnectionContext, Passivable { @@ -15,6 +19,14 @@ public class NettyConnectionContext implements ConnectionContext, Passivable { @Setter private ChannelHandlerContext ctx; + /** + * @deprecated костыль + */ + @Deprecated + @Getter + @Setter + private boolean usedContext; + @Override public State getState() { return ctx.channel().attr(NetworkAttributes.STATE).get(); @@ -25,6 +37,27 @@ public class NettyConnectionContext implements ConnectionContext, Passivable { ctx.channel().attr(NetworkAttributes.STATE).set(state); } + /** + * @deprecated костыль + */ + @Deprecated + @Override + public void setCustomProperty(String key, T value) { + Map map = ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get(); + map.put(key, value); + } + + /** + * @deprecated костыль + */ + @Deprecated + @SuppressWarnings("unchecked") + @Override + public Optional getCustomProperty(String key, Class classResult) { + Map map = ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get(); + return (Optional) Optional.ofNullable(map.getOrDefault(key, null)); + } + @Override public void send(ServerSidePacket packet) { ctx.write(packet); diff --git a/protocol/src/main/java/mc/protocol/NetworkAttributes.java b/protocol/src/main/java/mc/protocol/NetworkAttributes.java index 0be033c..b6a543b 100644 --- a/protocol/src/main/java/mc/protocol/NetworkAttributes.java +++ b/protocol/src/main/java/mc/protocol/NetworkAttributes.java @@ -3,8 +3,16 @@ package mc.protocol; import io.netty.util.AttributeKey; import lombok.experimental.UtilityClass; +import java.util.Map; + @UtilityClass public class NetworkAttributes { public static final AttributeKey STATE = AttributeKey.newInstance("STATE"); + + /** + * @deprecated костыль + */ + @Deprecated + public static final AttributeKey> CUSTOM_PROPERTIES = AttributeKey.newInstance("CUSTOM_PROPERTIES"); } diff --git a/protocol/src/main/java/mc/protocol/PacketInboundHandler.java b/protocol/src/main/java/mc/protocol/PacketInboundHandler.java index d567021..712a833 100644 --- a/protocol/src/main/java/mc/protocol/PacketInboundHandler.java +++ b/protocol/src/main/java/mc/protocol/PacketInboundHandler.java @@ -28,7 +28,9 @@ public class PacketInboundHandler extends SimpleChannelInboundHandler void setCustomProperty(String key, T value); + + /** + * @deprecated костыль + */ + @Deprecated + Optional getCustomProperty(String key, Class classResult); + void send(ServerSidePacket packet); void sendNow(ServerSidePacket packet); void flushSending(); diff --git a/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java b/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java index 1e2e6ab..5f4f7b8 100644 --- a/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java +++ b/protocol/src/main/java/mc/protocol/io/codec/ProtocolDecoder.java @@ -17,6 +17,7 @@ import mc.protocol.pool.PacketPool; import org.apache.commons.pool2.ObjectPool; import javax.annotation.Nonnull; +import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.function.Consumer; @@ -36,6 +37,8 @@ public class ProtocolDecoder extends ByteToMessageDecoder { @Override public void channelActive(@Nonnull ChannelHandlerContext ctx) throws Exception { + ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).set(new HashMap<>()); + NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx); consumerNewConnection.accept(context); @@ -48,6 +51,9 @@ public class ProtocolDecoder extends ByteToMessageDecoder { NettyConnectionContext context = poolNettyConnectionContext.borrowObject().setCtx(ctx); consumerDisconnect.accept(context); + ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).get().clear(); + ctx.channel().attr(NetworkAttributes.CUSTOM_PROPERTIES).set(null); + poolNettyConnectionContext.returnObject(context); super.channelInactive(ctx); } diff --git a/server/src/main/java/mc/server/Main.java b/server/src/main/java/mc/server/Main.java index 3f943c7..ea5e5d8 100644 --- a/server/src/main/java/mc/server/Main.java +++ b/server/src/main/java/mc/server/Main.java @@ -20,6 +20,7 @@ import mc.server.config.Config; import mc.server.di.ConfigModule; import mc.server.di.DaggerServerComponent; import mc.server.di.ServerComponent; +import mc.server.service.PlayerManager; import org.apache.commons.io.IOUtils; import org.slf4j.LoggerFactory; @@ -48,6 +49,7 @@ public class Main { .build(); Config config = serverComponent.getConfig(); + PlayerManager playerManager = serverComponent.getPlayerManager(); ProtocolComponent protocolComponent = DaggerProtocolComponent.builder() .protocolModule(new ProtocolModule(true)) @@ -57,7 +59,10 @@ public class Main { PacketHandler packetHandler = serverComponent.getPacketHandler(); server.onNewConnect(connectionContext -> connectionContext.setState(State.HANDSHAKING)); - server.onDisonnect(connectionContext -> connectionContext.setState(null)); + server.onDisonnect(connectionContext -> { + connectionContext.setState(null); + connectionContext.getCustomProperty("player", Player.class).ifPresent(playerManager::remove); + }); server.listenPacket(State.HANDSHAKING, HandshakePacket.class, packetHandler::onHandshake); server.listenPacket(State.STATUS, KeepAlivePacket.class, packetHandler::onKeepAlive); diff --git a/server/src/main/java/mc/server/PacketHandler.java b/server/src/main/java/mc/server/PacketHandler.java index 20ed7c9..4de5093 100644 --- a/server/src/main/java/mc/server/PacketHandler.java +++ b/server/src/main/java/mc/server/PacketHandler.java @@ -18,6 +18,7 @@ import mc.protocol.utils.GameMode; import mc.protocol.world.Chunk; import mc.protocol.world.World; import mc.server.config.Config; +import mc.server.service.PlayerManager; import org.apache.commons.io.IOUtils; import java.io.IOException; @@ -26,7 +27,6 @@ import java.nio.file.Path; import java.util.Base64; import java.util.Collections; import java.util.Random; -import java.util.UUID; import java.util.concurrent.TimeUnit; @Slf4j @@ -36,6 +36,7 @@ public class PacketHandler { private final Random random = new Random(System.currentTimeMillis()); private final Config config; private final World world; + private final PlayerManager playerManager; public void onHandshake(ConnectionContext context, HandshakePacket packet) { context.setState(packet.getNextState()); @@ -65,6 +66,8 @@ public class PacketHandler { serverInfo.players().max(config.players().maxOnlile()); if (config.players().fakeOnline().enable()) { serverInfo.players().online(config.players().fakeOnline().value()); + } else { + serverInfo.players().online(playerManager.online()); } serverInfo.players().sample(Collections.emptyList()); serverInfo.description(TextSerializer.fromPlain(config.motd())); @@ -81,16 +84,19 @@ public class PacketHandler { @SuppressWarnings("java:S2589") public void onLoginStart(ConnectionContext context, LoginStartPacket loginStartPacket) { + Player player = playerManager.addAndCreate(context, loginStartPacket.getName(), GameMode.SURVIVAL, world.getSpawn()); + context.setCustomProperty("player", player); + var loginSuccessPacket = new LoginSuccessPacket(); - loginSuccessPacket.setUuid(UUID.randomUUID()); - loginSuccessPacket.setName(loginStartPacket.getName()); + loginSuccessPacket.setUuid(player.getUuid()); + loginSuccessPacket.setName(player.getName()); context.sendNow(loginSuccessPacket); context.setState(State.PLAY); var joinGamePacket = new JoinGamePacket(); joinGamePacket.setEntityId(random.nextInt()); - joinGamePacket.setGameMode(GameMode.SURVIVAL); + joinGamePacket.setGameMode(player.getGameMode()); joinGamePacket.setDimension(0/*Overworld*/); joinGamePacket.setDifficulty(Difficulty.PEACEFUL); joinGamePacket.setLevelType(world.getLevelType()); @@ -98,7 +104,7 @@ public class PacketHandler { context.send(joinGamePacket); var spawnPositionPacket = new SpawnPositionPacket(); - spawnPositionPacket.setSpawn(world.getSpawn()); + spawnPositionPacket.setSpawn(player.getLocation()); context.send(spawnPositionPacket); @@ -114,7 +120,7 @@ public class PacketHandler { context.flushSending(); - Location chunkLocation = world.getSpawn().toChunkXZ(); + Location chunkLocation = player.getLocation().toChunkXZ(); Chunk chunk = world.getChunk(chunkLocation.getIntX(), chunkLocation.getIntZ()); var chunkDataPacket = new ChunkDataPacket(); @@ -145,7 +151,7 @@ public class PacketHandler { context.flushSending(); var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket(); - playerPositionAndLookPacket.setPosition(world.getSpawn()); + playerPositionAndLookPacket.setPosition(player.getLocation()); playerPositionAndLookPacket.setLook(new Look(0f, 0f)); playerPositionAndLookPacket.setTeleportId(random.nextInt()); diff --git a/server/src/main/java/mc/server/Player.java b/server/src/main/java/mc/server/Player.java new file mode 100644 index 0000000..2d93d70 --- /dev/null +++ b/server/src/main/java/mc/server/Player.java @@ -0,0 +1,20 @@ +package mc.server; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import mc.protocol.api.ConnectionContext; +import mc.protocol.model.Location; +import mc.protocol.utils.GameMode; + +import java.util.UUID; + +@RequiredArgsConstructor +@Getter +public class Player { + + private final ConnectionContext connectionContext; + private final UUID uuid; + private final String name; + private final GameMode gameMode; + private final Location location; +} diff --git a/server/src/main/java/mc/server/di/PacketHandlerModule.java b/server/src/main/java/mc/server/di/PacketHandlerModule.java index 750652c..fce9344 100644 --- a/server/src/main/java/mc/server/di/PacketHandlerModule.java +++ b/server/src/main/java/mc/server/di/PacketHandlerModule.java @@ -5,12 +5,13 @@ import dagger.Provides; import mc.protocol.world.World; import mc.server.PacketHandler; import mc.server.config.Config; +import mc.server.service.PlayerManager; @Module public class PacketHandlerModule { @Provides - public PacketHandler providePacketHandler(Config config, World world) { - return new PacketHandler(config, world); + public PacketHandler providePacketHandler(Config config, World world, PlayerManager playerManager) { + return new PacketHandler(config, world, playerManager); } } diff --git a/server/src/main/java/mc/server/di/PlayersModule.java b/server/src/main/java/mc/server/di/PlayersModule.java new file mode 100644 index 0000000..5d42a1b --- /dev/null +++ b/server/src/main/java/mc/server/di/PlayersModule.java @@ -0,0 +1,16 @@ +package mc.server.di; + +import dagger.Module; +import dagger.Provides; +import mc.protocol.di.ServerScope; +import mc.server.service.PlayerManager; + +@Module +public class PlayersModule { + + @Provides + @ServerScope + PlayerManager providePlayerManager() { + return new PlayerManager(); + } +} diff --git a/server/src/main/java/mc/server/di/ServerComponent.java b/server/src/main/java/mc/server/di/ServerComponent.java index ad89a4d..104eead 100644 --- a/server/src/main/java/mc/server/di/ServerComponent.java +++ b/server/src/main/java/mc/server/di/ServerComponent.java @@ -4,13 +4,15 @@ import dagger.Component; import mc.protocol.di.ServerScope; import mc.server.PacketHandler; import mc.server.config.Config; +import mc.server.service.PlayerManager; @Component(modules = { - ConfigModule.class, PacketHandlerModule.class, WorldModule.class + ConfigModule.class, PacketHandlerModule.class, WorldModule.class, PlayersModule.class }) @ServerScope public interface ServerComponent { Config getConfig(); PacketHandler getPacketHandler(); + PlayerManager getPlayerManager(); } diff --git a/server/src/main/java/mc/server/service/PlayerManager.java b/server/src/main/java/mc/server/service/PlayerManager.java new file mode 100644 index 0000000..8fe100e --- /dev/null +++ b/server/src/main/java/mc/server/service/PlayerManager.java @@ -0,0 +1,29 @@ +package mc.server.service; + +import mc.protocol.api.ConnectionContext; +import mc.protocol.model.Location; +import mc.protocol.utils.GameMode; +import mc.server.Player; + +import java.util.LinkedList; +import java.util.UUID; + +public class PlayerManager { + + private final LinkedList players = new LinkedList<>(); + + public Player addAndCreate(ConnectionContext context, String name, GameMode gameMode, Location location) { + context.setUsedContext(true); + Player player = new Player(context, UUID.randomUUID(), name, gameMode, location); + players.add(player); + return player; + } + + public void remove(Player player) { + players.remove(player); + } + + public int online() { + return players.size(); + } +} diff --git a/server/src/main/resources/config-sample.yml b/server/src/main/resources/config-sample.yml index bfb8600..169067b 100644 --- a/server/src/main/resources/config-sample.yml +++ b/server/src/main/resources/config-sample.yml @@ -11,7 +11,7 @@ disconnect-reason: '&4Server is not available.' players: max-online: 0 fake-online: - enable: true + enable: false value: 0 # Размер значка: 64x64 px