From ab17160f9de06a116ef43d0036beae712531b7bc Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 9 May 2021 18:41:31 +0300 Subject: [PATCH 1/4] config: add view-distance --- server/src/main/java/mc/server/config/Config.java | 8 ++++++++ server/src/main/java/mc/server/di/ConfigModule.java | 1 + server/src/main/resources/config-sample.yml | 5 ++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/mc/server/config/Config.java b/server/src/main/java/mc/server/config/Config.java index 07340fc..5d99eb4 100644 --- a/server/src/main/java/mc/server/config/Config.java +++ b/server/src/main/java/mc/server/config/Config.java @@ -15,6 +15,7 @@ public class Config { private final Server server = new Server(); private final Players players = new Players(); + private final World world = new World(); private String motd; private String disconnectReason; @@ -35,4 +36,11 @@ public class Config { private int maxOnlile; private int onlile; } + + @Getter + @Setter + @ToString + public static class World { + private int viewDistance; + } } diff --git a/server/src/main/java/mc/server/di/ConfigModule.java b/server/src/main/java/mc/server/di/ConfigModule.java index c4bd5b0..12bb65f 100644 --- a/server/src/main/java/mc/server/di/ConfigModule.java +++ b/server/src/main/java/mc/server/di/ConfigModule.java @@ -31,6 +31,7 @@ public class ConfigModule { config.disconnectReason(fromYamlPath("disconnect-reason", map, "")); config.players().maxOnlile(fromYamlPath("players/max-online", map, 0)); config.players().onlile(fromYamlPath("players/online", map, 0)); + config.world().viewDistance(fromYamlPath("world/view-distance", map, 0)); if (Boolean.TRUE.equals(fromYamlPath("icon/enable", map, false))) { config.iconPath(Paths.get(fromYamlPath("icon/path", map, "favicon.png"))); diff --git a/server/src/main/resources/config-sample.yml b/server/src/main/resources/config-sample.yml index c26428c..d96b359 100644 --- a/server/src/main/resources/config-sample.yml +++ b/server/src/main/resources/config-sample.yml @@ -15,4 +15,7 @@ players: # Размер значка: 64x64 px icon: enable: false - path: favicon.png \ No newline at end of file + path: favicon.png + +world: + view-distance: 1 \ No newline at end of file From 2b0ad9895b6be61e9dff2d2c80c522744476ce31 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 9 May 2021 18:42:33 +0300 Subject: [PATCH 2/4] add World, Chunk interfaces --- protocol/src/main/java/mc/protocol/world/Chunk.java | 7 +++++++ protocol/src/main/java/mc/protocol/world/World.java | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 protocol/src/main/java/mc/protocol/world/Chunk.java create mode 100644 protocol/src/main/java/mc/protocol/world/World.java diff --git a/protocol/src/main/java/mc/protocol/world/Chunk.java b/protocol/src/main/java/mc/protocol/world/Chunk.java new file mode 100644 index 0000000..ec4a551 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/world/Chunk.java @@ -0,0 +1,7 @@ +package mc.protocol.world; + +public interface Chunk { + + int getX(); + int getZ(); +} diff --git a/protocol/src/main/java/mc/protocol/world/World.java b/protocol/src/main/java/mc/protocol/world/World.java new file mode 100644 index 0000000..1d57700 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/world/World.java @@ -0,0 +1,13 @@ +package mc.protocol.world; + +import mc.protocol.model.Location; +import mc.protocol.utils.LevelType; + +public interface World { + + LevelType getLevelType(); + + Location getSpawn(); + + Chunk getChunk(int x, int z); +} From 20791ed88138dc2c598be6b7f9d6b98796fe1dde Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 9 May 2021 18:43:57 +0300 Subject: [PATCH 3/4] VoidWorld, VoidChunk --- .../packets/server/ChunkDataPacket.java | 41 ++++++++++++++++++- .../main/java/mc/server/world/VoidChunk.java | 13 ++++++ .../main/java/mc/server/world/VoidWorld.java | 26 ++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 server/src/main/java/mc/server/world/VoidChunk.java create mode 100644 server/src/main/java/mc/server/world/VoidWorld.java diff --git a/protocol/src/main/java/mc/protocol/packets/server/ChunkDataPacket.java b/protocol/src/main/java/mc/protocol/packets/server/ChunkDataPacket.java index ca0eba2..cfcac8d 100644 --- a/protocol/src/main/java/mc/protocol/packets/server/ChunkDataPacket.java +++ b/protocol/src/main/java/mc/protocol/packets/server/ChunkDataPacket.java @@ -28,13 +28,17 @@ import mc.protocol.packets.ServerSidePacket; @Data public class ChunkDataPacket implements ServerSidePacket { + private static NetByteBuf voidData; + private int x; private int z; + @SuppressWarnings("java:S125") @Override public void writeSelf(NetByteBuf netByteBuf) { netByteBuf.writeInt(x); netByteBuf.writeInt(z); + /* Временное отключение кода netByteBuf.writeBoolean(true); // Is Full chunk netByteBuf.writeVarInt(0b11111111); // Available Sections @@ -64,6 +68,41 @@ public class ChunkDataPacket implements ServerSidePacket { netByteBuf.writeVarInt(data.readableBytes()); // Size of Data netByteBuf.writeBytes(data); // Data netByteBuf.writeVarInt(0); // Number of block entities - /* write NBT's */ + // write NBT's + */ + + netByteBuf.writeBytes(voidData); + + voidData.resetReaderIndex(); + voidData.resetWriterIndex(); + } + + static { + voidData = new NetByteBuf(Unpooled.buffer()); + voidData.writeBoolean(true); // Is Full chunk + voidData.writeVarInt(0b11111111); // Available Sections + + NetByteBuf data = new NetByteBuf(Unpooled.buffer()); + for (int i = 0; i < 16; i++) { + NetByteBuf dataBuff = new NetByteBuf(Unpooled.wrappedBuffer(new byte[4096])); + NetByteBuf blockLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048])); + NetByteBuf skyLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048])); + NetByteBuf biomes = new NetByteBuf(Unpooled.wrappedBuffer(new byte[256])); + + data.writeUnsignedByte(13); + data.writeUnsignedByte(0); + data.writeVarInt(dataBuff.readableBytes()); + data.writeBytes(dataBuff); + data.writeBytes(blockLight); + data.writeBytes(skyLight); + data.writeBytes(biomes); + } + + voidData.writeVarInt(data.readableBytes()); + voidData.writeBytes(data); + voidData.writeVarInt(0); + + voidData.markReaderIndex(); + voidData.markWriterIndex(); } } diff --git a/server/src/main/java/mc/server/world/VoidChunk.java b/server/src/main/java/mc/server/world/VoidChunk.java new file mode 100644 index 0000000..3ee5cb6 --- /dev/null +++ b/server/src/main/java/mc/server/world/VoidChunk.java @@ -0,0 +1,13 @@ +package mc.server.world; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import mc.protocol.world.Chunk; + +@RequiredArgsConstructor +@Getter +public class VoidChunk implements Chunk { + + private final int x; + private final int z; +} diff --git a/server/src/main/java/mc/server/world/VoidWorld.java b/server/src/main/java/mc/server/world/VoidWorld.java new file mode 100644 index 0000000..a2df89b --- /dev/null +++ b/server/src/main/java/mc/server/world/VoidWorld.java @@ -0,0 +1,26 @@ +package mc.server.world; + +import mc.protocol.model.Location; +import mc.protocol.utils.LevelType; +import mc.protocol.world.Chunk; +import mc.protocol.world.World; + +public class VoidWorld implements World { + + private static final Location spawn = new Location(7d, 130d, 7d); + + @Override + public LevelType getLevelType() { + return LevelType.FLAT; + } + + @Override + public Location getSpawn() { + return VoidWorld.spawn; + } + + @Override + public Chunk getChunk(int x, int z) { + return new VoidChunk(x, z); + } +} From 04316d9cbdefd68c4d7ed52cbbccbd5422a379f5 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sun, 9 May 2021 18:47:51 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=B3=D1=80=D1=83=D0=B7=D0=B8=D0=BC=20?= =?UTF-8?q?=D1=87=D0=B0=D0=BD=D0=BA=D0=B8=20=D0=BF=D1=80=D0=B8=20=D0=B2?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/mc/protocol/model/Location.java | 12 +++++ .../main/java/mc/server/PacketHandler.java | 45 ++++++++++++++----- .../mc/server/di/PacketHandlerModule.java | 5 ++- .../java/mc/server/di/ServerComponent.java | 4 +- .../main/java/mc/server/di/WorldModule.java | 17 +++++++ 5 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 server/src/main/java/mc/server/di/WorldModule.java diff --git a/protocol/src/main/java/mc/protocol/model/Location.java b/protocol/src/main/java/mc/protocol/model/Location.java index 697f64b..483db15 100644 --- a/protocol/src/main/java/mc/protocol/model/Location.java +++ b/protocol/src/main/java/mc/protocol/model/Location.java @@ -9,4 +9,16 @@ public class Location { private double x; private double y; private double z; + + public int getIntX() { + return (int) x; + } + + public int getIntZ() { + return (int) z; + } + + public Location toChunkXZ() { + return new Location(this.getIntX() >> 4, 0d, this.getIntZ() >> 4); + } } diff --git a/server/src/main/java/mc/server/PacketHandler.java b/server/src/main/java/mc/server/PacketHandler.java index 8a97201..11ae54f 100644 --- a/server/src/main/java/mc/server/PacketHandler.java +++ b/server/src/main/java/mc/server/PacketHandler.java @@ -15,7 +15,8 @@ import mc.protocol.packets.server.*; import mc.protocol.serializer.TextSerializer; import mc.protocol.utils.Difficulty; import mc.protocol.utils.GameMode; -import mc.protocol.utils.LevelType; +import mc.protocol.world.Chunk; +import mc.protocol.world.World; import mc.server.config.Config; import org.apache.commons.io.IOUtils; @@ -34,6 +35,7 @@ public class PacketHandler { private final Random random = new Random(System.currentTimeMillis()); private final Config config; + private final World world; public void onHandshake(ConnectionContext context, HandshakePacket packet) { context.setState(packet.getNextState()); @@ -75,6 +77,7 @@ public class PacketHandler { context.sendNow(response); } + @SuppressWarnings("java:S2589") public void onLoginStart(ConnectionContext context, LoginStartPacket loginStartPacket) { var loginSuccessPacket = new LoginSuccessPacket(); loginSuccessPacket.setUuid(UUID.randomUUID()); @@ -88,14 +91,12 @@ public class PacketHandler { joinGamePacket.setGameMode(GameMode.SURVIVAL); joinGamePacket.setDimension(0/*Overworld*/); joinGamePacket.setDifficulty(Difficulty.PEACEFUL); - joinGamePacket.setLevelType(LevelType.FLAT); + joinGamePacket.setLevelType(world.getLevelType()); context.send(joinGamePacket); - Location spawnLocation = new Location(7d, 130d, 7d); - var spawnPositionPacket = new SpawnPositionPacket(); - spawnPositionPacket.setSpawn(spawnLocation); + spawnPositionPacket.setSpawn(world.getSpawn()); context.send(spawnPositionPacket); @@ -111,14 +112,38 @@ public class PacketHandler { context.flushSending(); - var chunkDataPacket = new ChunkDataPacket(); - chunkDataPacket.setX(0); - chunkDataPacket.setZ(0); + Location chunkLocation = world.getSpawn().toChunkXZ(); + Chunk chunk = world.getChunk(chunkLocation.getIntX(), chunkLocation.getIntZ()); - context.sendNow(chunkDataPacket); + var chunkDataPacket = new ChunkDataPacket(); + chunkDataPacket.setX(chunk.getX()); + chunkDataPacket.setZ(chunk.getZ()); + + context.send(chunkDataPacket); + + for (int i = 1; i <= config.world().viewDistance(); i++) { + int minX = chunkLocation.getIntX() - i; + int minZ = chunkLocation.getIntZ() - i; + int maxX = chunkLocation.getIntX() + i; + int maxZ = chunkLocation.getIntZ() + i; + + for (int z = minZ; z <= maxZ; z++) { + for (int x = minX; x <= maxX; x++) { + if ((z == minZ || z == maxZ) || (x == minX || x == maxX)) { + chunkDataPacket = new ChunkDataPacket(); + chunkDataPacket.setX(x); + chunkDataPacket.setZ(z); + + context.send(chunkDataPacket); + } + } + } + } + + context.flushSending(); var playerPositionAndLookPacket = new SPlayerPositionAndLookPacket(); - playerPositionAndLookPacket.setPosition(spawnLocation); + playerPositionAndLookPacket.setPosition(world.getSpawn()); playerPositionAndLookPacket.setLook(new Look(0f, 0f)); playerPositionAndLookPacket.setTeleportId(random.nextInt()); diff --git a/server/src/main/java/mc/server/di/PacketHandlerModule.java b/server/src/main/java/mc/server/di/PacketHandlerModule.java index d90f3a7..750652c 100644 --- a/server/src/main/java/mc/server/di/PacketHandlerModule.java +++ b/server/src/main/java/mc/server/di/PacketHandlerModule.java @@ -2,6 +2,7 @@ package mc.server.di; import dagger.Module; import dagger.Provides; +import mc.protocol.world.World; import mc.server.PacketHandler; import mc.server.config.Config; @@ -9,7 +10,7 @@ import mc.server.config.Config; public class PacketHandlerModule { @Provides - public PacketHandler providePacketHandler(Config config) { - return new PacketHandler(config); + public PacketHandler providePacketHandler(Config config, World world) { + return new PacketHandler(config, world); } } diff --git a/server/src/main/java/mc/server/di/ServerComponent.java b/server/src/main/java/mc/server/di/ServerComponent.java index 9b7ec2e..ad89a4d 100644 --- a/server/src/main/java/mc/server/di/ServerComponent.java +++ b/server/src/main/java/mc/server/di/ServerComponent.java @@ -1,12 +1,14 @@ package mc.server.di; import dagger.Component; +import mc.protocol.di.ServerScope; import mc.server.PacketHandler; import mc.server.config.Config; @Component(modules = { - ConfigModule.class, PacketHandlerModule.class + ConfigModule.class, PacketHandlerModule.class, WorldModule.class }) +@ServerScope public interface ServerComponent { Config getConfig(); diff --git a/server/src/main/java/mc/server/di/WorldModule.java b/server/src/main/java/mc/server/di/WorldModule.java new file mode 100644 index 0000000..b2ecf19 --- /dev/null +++ b/server/src/main/java/mc/server/di/WorldModule.java @@ -0,0 +1,17 @@ +package mc.server.di; + +import dagger.Module; +import dagger.Provides; +import mc.protocol.di.ServerScope; +import mc.protocol.world.World; +import mc.server.world.VoidWorld; + +@Module +public class WorldModule { + + @Provides + @ServerScope + public World provideWorld() { + return new VoidWorld(); + } +}