From d699dae60111ce6e5cf55b9ebeee13772a5df2ff Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Wed, 1 Aug 2018 09:36:36 +0300 Subject: [PATCH 01/15] stash 1 --- .../mc/core/network/proto_1_12_2/State.java | 1 + .../proto_1_12_2/packets/ChunkDataPacket.java | 58 +++++++++++++++++++ .../netty/handlers/LoginHandler.java | 8 +++ 3 files changed, 67 insertions(+) create mode 100644 proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/State.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/State.java index 237aa4f..feb4f26 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/State.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/State.java @@ -87,6 +87,7 @@ public enum State { .put(PluginMessagePacket.class, 0x18) .put(ChangeGameState.class, 0x1E) .put(KeepAlivePacket.class, 0x1F) + .put(ChunkDataPacket.class, 0x20) .put(JoinGamePacket.class, 0x23) .put(PlayerAbilitiesPacket.class, 0x2C) .put(PlayerListItemPacket.class, 0x2E) diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java new file mode 100644 index 0000000..c05c479 --- /dev/null +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java @@ -0,0 +1,58 @@ +/* + * DmitriyMX + * 2018-07-21 + */ +package mc.core.network.proto_1_12_2.packets; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.extern.slf4j.Slf4j; +import mc.core.network.NetOutputStream; +import mc.core.network.SCPacket; +import mc.core.world.Chunk; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@NoArgsConstructor +public class ChunkDataPacket implements SCPacket { + @Setter + private int x; + @Setter + private int z; + @Setter + private boolean initChunk = true; // "Ground-Up Continuous" + @Getter + private List chunks = new ArrayList<>(); + + @Override + public void writeSelf(NetOutputStream netStream) { + netStream.writeInt(x); + netStream.writeInt(z); + netStream.writeBoolean(initChunk); + netStream.writeVarInt(0b11111111); // Primary Bit Mask + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + for (Chunk chunk : chunks) { + netStream.writeByte(4); // Bits Per Block + // + // + // + // + // +// baos.write(ChunkSerializer.serializeBiomes(chunk)); + } + } catch (IOException e) { + log.error("Error serialize chunk", e); // what? is it possible?? + } + netStream.writeVarInt(baos.size()); // Size of Data in bytes + netStream.writeBytes(baos.toByteArray()); // Data chunks + netStream.writeVarInt(0); // size NBT + /* writeNBT */ + } +} diff --git a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java index eb5cd65..4ceb337 100644 --- a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java +++ b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java @@ -80,6 +80,14 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand channel.write(pkt3); channel.flush(); + // Send chunk data + ChunkDataPacket pkt8 = new ChunkDataPacket(); + pkt8.setX(0); + pkt8.setZ(0); + pkt8.getChunks().add(world.getChunk(0,0)); + pkt8.setInitChunk(true); + channel.writeAndFlush(pkt8); + // Player Position And Look PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket(); pkt4.setLocation(player.getLocation()); From 0152377289a07748187ada538feedd9575521d01 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Thu, 2 Aug 2018 14:25:29 +0300 Subject: [PATCH 02/15] stash 2 --- core/src/main/java/mc/core/world/Block.java | 15 ++++ core/src/main/java/mc/core/world/Chunk.java | 15 ++-- .../ByteArrayOutputNetStream.java | 4 ++ .../proto_1_12_2/packets/ChunkDataPacket.java | 71 +++++++++++++++---- 4 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 core/src/main/java/mc/core/world/Block.java diff --git a/core/src/main/java/mc/core/world/Block.java b/core/src/main/java/mc/core/world/Block.java new file mode 100644 index 0000000..ba2865a --- /dev/null +++ b/core/src/main/java/mc/core/world/Block.java @@ -0,0 +1,15 @@ +/* + * DmitriyMX + * 2018-08-02 + */ +package mc.core.world; + +import mc.core.Location; + +public interface Block { + int getId(); + int getState(); + int getMetadata(); + int getLight(); + Location getLocation(); +} diff --git a/core/src/main/java/mc/core/world/Chunk.java b/core/src/main/java/mc/core/world/Chunk.java index 15ee0fa..db8f289 100644 --- a/core/src/main/java/mc/core/world/Chunk.java +++ b/core/src/main/java/mc/core/world/Chunk.java @@ -4,16 +4,15 @@ */ package mc.core.world; +import mc.core.Location; + /* 16x16x16 */ public interface Chunk { - int getBlockType(int x, int y, int z); - void setBlockType(int x, int y, int z, int type); - - int getBlockMetadata(int x, int y, int z); - void setBlockMetadata(int x, int y, int z, int metadata); - - int getBlockLight(int x, int y, int z); - void setBlockLight(int x, int y, int z, int lightLevel); + Block getBlock(int x, int y, int z); + default Block getBlock(Location location) { + return getBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + void setBlock(Block block); int getSkyLight(int x, int y, int z); void setSkyLight(int x, int y, int z, int lightLevel); diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/ByteArrayOutputNetStream.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/ByteArrayOutputNetStream.java index 15810b7..d496e05 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/ByteArrayOutputNetStream.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/ByteArrayOutputNetStream.java @@ -65,6 +65,10 @@ public class ByteArrayOutputNetStream extends NetOutputStream_p340 { writeLong(Double.doubleToLongBits(value)); } + public int size() { + return baos.size(); + } + public byte[] toByteArray() { return baos.toByteArray(); } diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java index c05c479..f1e9f98 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java @@ -10,6 +10,7 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import mc.core.network.NetOutputStream; import mc.core.network.SCPacket; +import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream; import mc.core.world.Chunk; import java.io.ByteArrayOutputStream; @@ -17,6 +18,55 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; +/* +Packet structure + +- https://wiki.vg/Chunk_Format#Packet_structure + ++------------------------------------------------------+ +| Field | Type | +|--------------------------|---------------------------| +| Chunk X | int | +|--------------------------|---------------------------| +| Chunk Y | int | +|--------------------------|---------------------------| +| Init Chunk | boolean | ("Ground-Up Continuous") +|--------------------------|---------------------------| +| Primary Bit Mask | VarInt | +|--------------------------|---------------------------| +| Size of Data | VarInt | +|--------------------------|---------------------------| +| Data | Byte array | - https://wiki.vg/Chunk_Format#Data_structure +| +------------------------------------------------+ | +| | Chunk Section | Byte array | | - https://wiki.vg/Chunk_Format#Chunk_Section_structure +| | +------------------------------------------+ | | +| | | Bits Per Block | Unsigned Byte | | | +| | |--------------------|---------------------| | | +| | | Palette | Byte array | | | - https://wiki.vg/Chunk_Format#Palettes +| | | +------------------------------------+ | | | (we use Indirect type palette) +| | | | Size of palette | VarInt | | | | +| | | |-----------------|------------------| | | | +| | | | Palette | Array of VarInt | | | | +| | | +------------------------------------+ | | | +| | |--------------------|---------------------| | | +| | | Size of Data Array | VarInt | | | +| | |--------------------|---------------------| | | +| | | Data Array | Array of Long | | | +| | |--------------------|---------------------| | | +| | | Block Light | Byte Array | | | +| | |--------------------|---------------------| | | +| | | Sky Light | Optional Byte Array | | | +| | +------------------------------------------+ | | +| |-----------------------|------------------------| | +| | Biomes | Optional Byte array | | +| +------------------------------------------------+ | +|--------------------------|---------------------------| +| Number of block entities | VarInt | +|--------------------------|---------------------------| +| Block entities | Array of NBT | ++------------------------------------------------------+ + */ + @Slf4j @NoArgsConstructor public class ChunkDataPacket implements SCPacket { @@ -36,19 +86,14 @@ public class ChunkDataPacket implements SCPacket { netStream.writeBoolean(initChunk); netStream.writeVarInt(0b11111111); // Primary Bit Mask - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - for (Chunk chunk : chunks) { - netStream.writeByte(4); // Bits Per Block - // - // - // - // - // -// baos.write(ChunkSerializer.serializeBiomes(chunk)); - } - } catch (IOException e) { - log.error("Error serialize chunk", e); // what? is it possible?? + ByteArrayOutputNetStream baos = new ByteArrayOutputNetStream(); + for (Chunk chunk : chunks) { + // + // + // + // + // + // } netStream.writeVarInt(baos.size()); // Size of Data in bytes netStream.writeBytes(baos.toByteArray()); // Data chunks From 55ef6eec6650d8053a1ea12a414e4c41036ec0df Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Thu, 2 Aug 2018 15:59:11 +0300 Subject: [PATCH 03/15] stash 3 --- .../proto_1_12_2/packets/ChunkDataPacket.java | 94 +++++++++++++++---- 1 file changed, 78 insertions(+), 16 deletions(-) diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java index f1e9f98..af8789f 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import mc.core.network.NetOutputStream; import mc.core.network.SCPacket; import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream; +import mc.core.world.Block; import mc.core.world.Chunk; import java.io.ByteArrayOutputStream; @@ -40,7 +41,7 @@ Packet structure | +------------------------------------------------+ | | | Chunk Section | Byte array | | - https://wiki.vg/Chunk_Format#Chunk_Section_structure | | +------------------------------------------+ | | -| | | Bits Per Block | Unsigned Byte | | | +| | | Bits Per Block | Unsigned Byte | | | (we use 4 bits per block) | | |--------------------|---------------------| | | | | | Palette | Byte array | | | - https://wiki.vg/Chunk_Format#Palettes | | | +------------------------------------+ | | | (we use Indirect type palette) @@ -53,9 +54,9 @@ Packet structure | | |--------------------|---------------------| | | | | | Data Array | Array of Long | | | | | |--------------------|---------------------| | | -| | | Block Light | Byte Array | | | +| | | Block Light | Byte Array | | | (Half byte per block) | | |--------------------|---------------------| | | -| | | Sky Light | Optional Byte Array | | | +| | | Sky Light | Optional Byte Array | | | (Only if in the Overworld; half byte per block) | | +------------------------------------------+ | | | |-----------------------|------------------------| | | | Biomes | Optional Byte array | | @@ -79,25 +80,86 @@ public class ChunkDataPacket implements SCPacket { @Getter private List chunks = new ArrayList<>(); + private long serializeBlockState(Block block) { + return (block.getId() << 4) | block.getState(); + } + @Override public void writeSelf(NetOutputStream netStream) { - netStream.writeInt(x); - netStream.writeInt(z); - netStream.writeBoolean(initChunk); + netStream.writeInt(x); // Chunk X + netStream.writeInt(z); // Chunk Y + netStream.writeBoolean(initChunk); // Init Chunk netStream.writeVarInt(0b11111111); // Primary Bit Mask - ByteArrayOutputNetStream baos = new ByteArrayOutputNetStream(); + final ByteArrayOutputNetStream data = new ByteArrayOutputNetStream(); + for (Chunk chunk : chunks) { - // - // - // - // - // - // + final List palette = new ArrayList<>(); + final ByteArrayOutputNetStream dataArray = new ByteArrayOutputNetStream(); + final ByteArrayOutputNetStream blockLight = new ByteArrayOutputNetStream(); + final ByteArrayOutputNetStream skyLight = new ByteArrayOutputNetStream(); + final ByteArrayOutputNetStream biomes = new ByteArrayOutputNetStream(); + + int blockLightCompacted = 0; + boolean flagFirstHalf = true; + + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + Block block = chunk.getBlock(x, y, z); + long blockState = serializeBlockState(block); + + int currentIndexPaletteBlock; + if (!palette.contains(blockState)) { + palette.add(blockState); + currentIndexPaletteBlock = palette.size()-1; + } else { + currentIndexPaletteBlock = palette.indexOf(blockState); + } + + dataArray.writeLong(currentIndexPaletteBlock); + if (flagFirstHalf) { + blockLightCompacted = block.getLight(); + flagFirstHalf = false; + } else { + blockLightCompacted = (blockLightCompacted << 4) | block.getLight(); + blockLight.writeByte(blockLightCompacted); + flagFirstHalf = true; + skyLight.writeByte(0b11111111); //FIXME + } + + biomes.writeByte(chunk.getBiome(x, z)); + } + } + } + + // + // + data.writeUnsignedByte(4); // Bits Per Block + data.writeVarInt(palette.size()); // Size of palette + palette.stream() + .mapToInt(Long::intValue) + .forEach(data::writeVarInt); // Palette + // + // + data.writeVarInt(dataArray.size()); // Size of Data Array + data.writeBytes(dataArray.toByteArray()); // Data Array + // + // + data.writeBytes(blockLight.toByteArray()); + // + // + data.writeBytes(skyLight.toByteArray()); + // + // + // + data.writeBytes(biomes.toByteArray()); + // } - netStream.writeVarInt(baos.size()); // Size of Data in bytes - netStream.writeBytes(baos.toByteArray()); // Data chunks - netStream.writeVarInt(0); // size NBT + + netStream.writeVarInt(data.size()); // Size of Data + netStream.writeBytes(data.toByteArray()); // Data + netStream.writeVarInt(0); // Number of block entities /* writeNBT */ } } From 2bc4e5e1b5ddbce1dc6bfc5698e2ff762d19ce9a Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Thu, 2 Aug 2018 16:27:02 +0300 Subject: [PATCH 04/15] stash 4 --- .../network/proto_1_12_2/netty/handlers/LoginHandler.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java index 4ceb337..a0c9591 100644 --- a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java +++ b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java @@ -88,6 +88,14 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand pkt8.setInitChunk(true); channel.writeAndFlush(pkt8); + // One Chunk + ChunkDataPacket pkt9 = new ChunkDataPacket(); + pkt9.setInitChunk(true); + pkt9.setX(0); + pkt9.setZ(0); + pkt9.getChunks().add(world.getChunk(0, 0)); + channel.writeAndFlush(pkt9); + // Player Position And Look PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket(); pkt4.setLocation(player.getLocation()); From 3ffd621e022c57e1c3169e10dbcf970b18f3d88e Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Thu, 2 Aug 2018 21:13:54 +0300 Subject: [PATCH 05/15] stash 5 --- .../main/java/mc/world/flat/SimpleBlock.java | 20 ++++++++++ .../main/java/mc/world/flat/SimpleChunk.java | 40 ++++++------------- 2 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 flat_world/src/main/java/mc/world/flat/SimpleBlock.java diff --git a/flat_world/src/main/java/mc/world/flat/SimpleBlock.java b/flat_world/src/main/java/mc/world/flat/SimpleBlock.java new file mode 100644 index 0000000..5691732 --- /dev/null +++ b/flat_world/src/main/java/mc/world/flat/SimpleBlock.java @@ -0,0 +1,20 @@ +/* + * DmitriyMX + * 2018-08-02 + */ +package mc.world.flat; + +import lombok.Getter; +import lombok.Setter; +import mc.core.Location; +import mc.core.world.Block; + +@Getter +@Setter +public class SimpleBlock implements Block { + private int id; + private int state; + private int metadata; + private int light; + private Location location; +} diff --git a/flat_world/src/main/java/mc/world/flat/SimpleChunk.java b/flat_world/src/main/java/mc/world/flat/SimpleChunk.java index 5186615..a44c23a 100644 --- a/flat_world/src/main/java/mc/world/flat/SimpleChunk.java +++ b/flat_world/src/main/java/mc/world/flat/SimpleChunk.java @@ -4,40 +4,26 @@ */ package mc.world.flat; +import mc.core.world.Block; import mc.core.world.Chunk; public class SimpleChunk implements Chunk { @Override - public int getBlockType(int x, int y, int z) { - if (y == 0) return 7; - else if (y >= 1 && y <= 2) return 3; - else if (y == 3) return 2; - else return 0; + public Block getBlock(int x, int y, int z) { + SimpleBlock block = new SimpleBlock(); + block.setMetadata(0); + block.setLight(0); + + if (y == 0) block.setId(7); + else if (y >= 1 && y <= 2) block.setId(3); + else if (y == 3) block.setId(2); + else block.setId(0); + + return block; } @Override - public void setBlockType(int x, int y, int z, int type) { - - } - - @Override - public int getBlockMetadata(int x, int y, int z) { - return 0; - } - - @Override - public void setBlockMetadata(int x, int y, int z, int metadata) { - - } - - @Override - public int getBlockLight(int x, int y, int z) { - return 0; - } - - @Override - public void setBlockLight(int x, int y, int z, int lightLevel) { - + public void setBlock(Block block) { } @Override From 761aff33108beb1558d110f3f15a8f16063e2016 Mon Sep 17 00:00:00 2001 From: Forwolk Date: Sat, 4 Aug 2018 16:20:40 +0300 Subject: [PATCH 06/15] Water biomes --- core/src/main/java/mc/core/world/Biome.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/src/main/java/mc/core/world/Biome.java b/core/src/main/java/mc/core/world/Biome.java index 5a60047..71a0fad 100644 --- a/core/src/main/java/mc/core/world/Biome.java +++ b/core/src/main/java/mc/core/world/Biome.java @@ -2,6 +2,8 @@ package mc.core.world; import lombok.Getter; +import java.util.EnumSet; + public enum Biome { OCEAN(0, "Ocean", 0x0000cd), PLAINS(1, "Plains", 0x008000), @@ -38,6 +40,8 @@ public enum Biome { @Getter private final int color; + private final static EnumSet waterBiomes = EnumSet.of(OCEAN, RIVER, FROZEN_OCEAN, FROZEN_RIVER, DEEP_OCEAN); + Biome(int id, String name, int color) { this.id = id; this.name = name; @@ -47,4 +51,8 @@ public enum Biome { public static Biome getById(int id) { return Biome.values()[id]; } + + public static boolean isWaterBiome (Biome biome) { + return waterBiomes.contains(biome); + } } From 420635476055df7cab67725713663a722753e1b1 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sat, 4 Aug 2018 15:10:51 +0300 Subject: [PATCH 07/15] fix: NetOutputStream.writeVarInt() --- .../proto_1_12_2/NetOutputStream_p340.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/NetOutputStream_p340.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/NetOutputStream_p340.java index ea609cf..cbc3239 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/NetOutputStream_p340.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/NetOutputStream_p340.java @@ -14,17 +14,16 @@ import java.util.UUID; public abstract class NetOutputStream_p340 extends NetOutputStream { @Override public void writeVarInt(int value) { - do { - byte temp = (byte)(value & 0b01111111); - // Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone + while ((value & -128) != 0) { + writeByte(value & 127 | 128); value >>>= 7; - if (value != 0) { - temp |= 0b10000000; - } - writeByte(temp); - } while (value != 0); + } + + writeByte(value); } + + @Override public void writeString(String value) { if (value.length() > Short.MAX_VALUE) { From 1b4f2f8eac43d287bd9301fa57362afea5600825 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sat, 4 Aug 2018 18:40:11 +0300 Subject: [PATCH 08/15] fix: ChunkDataPacket Many thanks Forwolk! --- .../proto_1_12_2/packets/ChunkDataPacket.java | 61 +++++++++++++------ 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java index af8789f..aecbbc6 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java @@ -8,14 +8,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import mc.core.Location; import mc.core.network.NetOutputStream; import mc.core.network.SCPacket; import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream; import mc.core.world.Block; import mc.core.world.Chunk; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.io.*; import java.util.ArrayList; import java.util.List; @@ -80,8 +80,8 @@ public class ChunkDataPacket implements SCPacket { @Getter private List chunks = new ArrayList<>(); - private long serializeBlockState(Block block) { - return (block.getId() << 4) | block.getState(); + private int serializeBlockState(int id, int state) { + return (id << 4) | state; } @Override @@ -89,25 +89,33 @@ public class ChunkDataPacket implements SCPacket { netStream.writeInt(x); // Chunk X netStream.writeInt(z); // Chunk Y netStream.writeBoolean(initChunk); // Init Chunk - netStream.writeVarInt(0b11111111); // Primary Bit Mask + netStream.writeVarInt(0b00000001); // Primary Bit Mask final ByteArrayOutputNetStream data = new ByteArrayOutputNetStream(); + int dataItems = 0; + final int airBlockPalette = serializeBlockState(0, 0); for (Chunk chunk : chunks) { - final List palette = new ArrayList<>(); + final List palette = new ArrayList<>(); + palette.add(airBlockPalette); final ByteArrayOutputNetStream dataArray = new ByteArrayOutputNetStream(); final ByteArrayOutputNetStream blockLight = new ByteArrayOutputNetStream(); final ByteArrayOutputNetStream skyLight = new ByteArrayOutputNetStream(); final ByteArrayOutputNetStream biomes = new ByteArrayOutputNetStream(); + long dataValueCompacted = 0; int blockLightCompacted = 0; - boolean flagFirstHalf = true; + int skyLightCompacted = 0; + + int idxHalfLong = 0; + int idxHalfByte = 0; + boolean biomeFinally = false; for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { Block block = chunk.getBlock(x, y, z); - long blockState = serializeBlockState(block); + int blockState = serializeBlockState(block.getId(), block.getState()); int currentIndexPaletteBlock; if (!palette.contains(blockState)) { @@ -117,18 +125,37 @@ public class ChunkDataPacket implements SCPacket { currentIndexPaletteBlock = palette.indexOf(blockState); } - dataArray.writeLong(currentIndexPaletteBlock); - if (flagFirstHalf) { + if (idxHalfLong == 0) { + dataValueCompacted = currentIndexPaletteBlock; + idxHalfLong++; + } else if (idxHalfLong > 0 && idxHalfLong < 15) { + dataValueCompacted = (dataValueCompacted << 4) | currentIndexPaletteBlock; + idxHalfLong++; + } else { + dataValueCompacted = (dataValueCompacted << 4) | currentIndexPaletteBlock; + dataArray.writeLong(dataValueCompacted); + idxHalfLong = 0; + dataItems++; + } + + if (idxHalfByte == 0) { blockLightCompacted = block.getLight(); - flagFirstHalf = false; + skyLightCompacted = chunk.getSkyLight(x, y, z); + idxHalfByte++; } else { blockLightCompacted = (blockLightCompacted << 4) | block.getLight(); blockLight.writeByte(blockLightCompacted); - flagFirstHalf = true; - skyLight.writeByte(0b11111111); //FIXME + skyLightCompacted = (skyLightCompacted << 4) | chunk.getSkyLight(x, y, z); + skyLight.writeByte(skyLightCompacted); + idxHalfByte = 0; } - biomes.writeByte(chunk.getBiome(x, z)); + if (!biomeFinally) { + biomes.writeByte(chunk.getBiome(x, z)); + if (x == 15 && z == 15) { + biomeFinally = true; + } + } } } } @@ -137,12 +164,10 @@ public class ChunkDataPacket implements SCPacket { // data.writeUnsignedByte(4); // Bits Per Block data.writeVarInt(palette.size()); // Size of palette - palette.stream() - .mapToInt(Long::intValue) - .forEach(data::writeVarInt); // Palette + palette.forEach(data::writeVarInt); // Palette // // - data.writeVarInt(dataArray.size()); // Size of Data Array + data.writeVarInt(dataItems); // Size of Data Array data.writeBytes(dataArray.toByteArray()); // Data Array // // From 5d3487d5ecdd25e383aa5a47dc791448713f9559 Mon Sep 17 00:00:00 2001 From: Forwolk Date: Sun, 5 Aug 2018 17:10:21 +0300 Subject: [PATCH 09/15] Debug optimization --- .../generator/SeedBasedWorldGenerator.java | 119 +++--------------- 1 file changed, 19 insertions(+), 100 deletions(-) diff --git a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java index 8253165..3f272b0 100644 --- a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java +++ b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java @@ -6,9 +6,6 @@ import mc.core.block.BlockFactory; import mc.core.block.BlockType; import mc.core.world.*; import mc.world.generated_world.region.RegionImpl; -import mc.world.generated_world.serialization.ChunkSerializer; -import mc.world.generated_world.serialization.RegionReaderWriter; -import mc.world.generated_world.serialization.WorldReaderWriter; import mc.world.generated_world.world.CubicWorld; import mc.world.generated_world.world.Temperature; import mc.world.generated_world.world.Wetness; @@ -16,6 +13,7 @@ import mc.world.generated_world.world.Wetness; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; +import java.io.IOException; import java.util.UUID; import static mc.world.generated_world.WorldConstants.*; @@ -26,24 +24,26 @@ public class SeedBasedWorldGenerator implements WorldGenerator { public static void main(String[] args) throws Exception{ WorldGenerator worldGenerator = new SeedBasedWorldGenerator(); World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 2626949); - Region region = worldGenerator.generateRegion(0, 0, world); + /*Region region = worldGenerator.generateRegion(0, 0, world); region.save(new ChunkSerializer(), new RegionReaderWriter(new File("worlds", world.getWorldId().toString()))); - new WorldReaderWriter(new File("worlds")).writeWorldInfo(world); - /*worldGenerator.generateRegion(1, 0, world); - worldGenerator.generateRegion(-1, 0, world); - worldGenerator.generateRegion(0, 1, world); - worldGenerator.generateRegion(0, -1, world); - worldGenerator.generateRegion(-1, -1, world); - worldGenerator.generateRegion(1, -1, world); - worldGenerator.generateRegion(-1, 1, world); - worldGenerator.generateRegion(1, 1, world); + new WorldReaderWriter(new File("worlds")).writeWorldInfo(world);*/ + + createBigImage(worldGenerator, world); + } + + private static void createBigImage (WorldGenerator worldGenerator, World world) throws IOException { BufferedImage image = new BufferedImage(3 * 256, 3 * 256, BufferedImage.TYPE_INT_RGB); - BufferedImage currentImage; - int shiftX; - int shiftY; - currentImage = ImageIO.read(new File("out/0.0", "biomeMap.png")); - shiftX = 1; - shiftY = 1; + for (int x = 0; x <= 2; x ++) { + for (int z = 0; z <= 2; z ++) { + worldGenerator.generateRegion(x - 1, z - 1, world); + addToBigImage(x, z, image); + } + } + ImageIO.write(image, "png", new File("out", "merged.png")); + } + + private static void addToBigImage (int shiftX, int shiftY, BufferedImage image) throws IOException{ + BufferedImage currentImage = ImageIO.read(new File("out/" + (shiftX - 1) + "." + (shiftY - 1), "biomeMap.png")); for (int x = 0; x < 256; x ++){ for (int y = 0; y < 256; y ++){ int tx = 256 * shiftX + x; @@ -51,87 +51,6 @@ public class SeedBasedWorldGenerator implements WorldGenerator { image.setRGB(tx, ty, currentImage.getRGB(x, y)); } } - currentImage = ImageIO.read(new File("out/0.1", "biomeMap.png")); - shiftX = 1; - shiftY = 2; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/1.0", "biomeMap.png")); - shiftX = 2; - shiftY = 1; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/-1.0", "biomeMap.png")); - shiftX = 0; - shiftY = 1; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/0.-1", "biomeMap.png")); - shiftX = 1; - shiftY = 0; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/-1.-1", "biomeMap.png")); - shiftX = 0; - shiftY = 0; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/1.-1", "biomeMap.png")); - shiftX = 2; - shiftY = 0; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/1.1", "biomeMap.png")); - shiftX = 2; - shiftY = 2; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - currentImage = ImageIO.read(new File("out/-1.1", "biomeMap.png")); - shiftX = 0; - shiftY = 2; - for (int x = 0; x < 256; x ++){ - for (int y = 0; y < 256; y ++){ - int tx = 256 * shiftX + x; - int ty = 256 * shiftY + y; - image.setRGB(tx, ty, currentImage.getRGB(x, y)); - } - } - ImageIO.write(image, "png", new File("out", "merged.png"));*/ } @Override From 15b1ff7370528a865bc09bb09118c785abe5cb06 Mon Sep 17 00:00:00 2001 From: Forwolk Date: Sun, 5 Aug 2018 17:15:55 +0300 Subject: [PATCH 10/15] Noise generator in separate class --- .../generator/NoiseGenerator.java | 57 +++++++++++++++++++ .../generator/SeedBasedWorldGenerator.java | 52 +---------------- 2 files changed, 58 insertions(+), 51 deletions(-) create mode 100644 generated_world/src/main/java/mc/world/generated_world/generator/NoiseGenerator.java diff --git a/generated_world/src/main/java/mc/world/generated_world/generator/NoiseGenerator.java b/generated_world/src/main/java/mc/world/generated_world/generator/NoiseGenerator.java new file mode 100644 index 0000000..b3c84c7 --- /dev/null +++ b/generated_world/src/main/java/mc/world/generated_world/generator/NoiseGenerator.java @@ -0,0 +1,57 @@ +package mc.world.generated_world.generator; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import static mc.world.generated_world.WorldConstants.WORLD_REGION_SIZE; + +@Slf4j +@RequiredArgsConstructor +public class NoiseGenerator { + private int[] perm = new int[WORLD_REGION_SIZE]; + private double[] gradsX = new double[WORLD_REGION_SIZE]; + private double[] gradsY = new double[WORLD_REGION_SIZE]; + private final int seed; + + void init() { + for (int i = 0; i < WORLD_REGION_SIZE; ++i) { + int other = rand(i) % (i + 1); + if (i > other) + perm[i] = perm[other]; + perm[other] = i; + gradsX[i] = Math.cos(2.0f * Math.PI * i / WORLD_REGION_SIZE); + gradsY[i] = Math.sin(2.0f * Math.PI * i / WORLD_REGION_SIZE); + } + log.debug("Noise generator is initialized"); + } + + double f(double t) { + t = Math.abs(t); + return t >= 1.0f ? 0.0f : 1.0f - + (3.0f - 2.0f * t) * t * t; + } + + private double surflet(double x, double y, double gradX, double gradY) { + return f(x) * f(y) * (gradX * x + gradY * y); + } + + double noise(double x, double y) { + float result = 0.0f; + int cellX = (int)(x); + int cellY = (int)(y); + int mask = WORLD_REGION_SIZE - 1; + for (int gridY = cellY; gridY <= cellY + 1; ++gridY) + for (int gridX = cellX; gridX <= cellX + 1; ++gridX) { + int hash = perm[(perm[gridX & mask] + gridY) & mask]; + result += surflet(x - gridX, y - gridY, + gradsX[hash], gradsY[hash]); + } + return (result + 1) / 2; + } + + private int rand(int i) { + int x = (i * i) % WORLD_REGION_SIZE; + int y = (i + i * x) % WORLD_REGION_SIZE; + return (int) (Integer.MAX_VALUE * SeedRandomGenerator.random(x, y, seed)); + } +} diff --git a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java index 3f272b0..f1f63de 100644 --- a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java +++ b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java @@ -80,7 +80,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator { return 40960 + x; } - public void generate() { + private void generate() { log.debug("Starting generating region [{}, {}] for world '{}' with seed '{}'", region.getX(), region.getZ(), world.getWorldId(), world.getSeed()); noiseGenerator = new NoiseGenerator(world.getSeed()); @@ -388,54 +388,4 @@ public class SeedBasedWorldGenerator implements WorldGenerator { } } - @RequiredArgsConstructor - private class NoiseGenerator { - int mask = WORLD_REGION_SIZE - 1; - int[] perm = new int[WORLD_REGION_SIZE]; - double[] gradsX = new double[WORLD_REGION_SIZE]; - double[] gradsY = new double[WORLD_REGION_SIZE]; - private final int seed; - - void init() { - for (int i = 0; i < WORLD_REGION_SIZE; ++i) { - int other = rand(i) % (i + 1); - if (i > other) - perm[i] = perm[other]; - perm[other] = i; - gradsX[i] = Math.cos(2.0f * Math.PI * i / WORLD_REGION_SIZE); - gradsY[i] = Math.sin(2.0f * Math.PI * i / WORLD_REGION_SIZE); - } - log.debug("Noise generator is initialized"); - } - - double f(double t) { - t = Math.abs(t); - return t >= 1.0f ? 0.0f : 1.0f - - (3.0f - 2.0f * t) * t * t; - } - - double surflet(double x, double y, double gradX, double gradY) { - return f(x) * f(y) * (gradX * x + gradY * y); - } - - double noise(double x, double y) { - float result = 0.0f; - int cellX = (int)(x); - int cellY = (int)(y); - for (int gridY = cellY; gridY <= cellY + 1; ++gridY) - for (int gridX = cellX; gridX <= cellX + 1; ++gridX) { - int hash = perm[(perm[gridX & mask] + gridY) & mask]; - result += surflet(x - gridX, y - gridY, - gradsX[hash], gradsY[hash]); - } - return (result + 1) / 2; - } - - int rand(int i) { - int x = (i * i) % WORLD_REGION_SIZE; - int y = (i + i * x) % WORLD_REGION_SIZE; - return (int) (Integer.MAX_VALUE * SeedRandomGenerator.random(x, y, seed)); - } - } - } \ No newline at end of file From ff71892fcb47ec5d0e39add4377751f23480d5e4 Mon Sep 17 00:00:00 2001 From: Forwolk Date: Sun, 5 Aug 2018 17:51:24 +0300 Subject: [PATCH 11/15] Biomes refactoring --- core/src/main/java/mc/core/world/Biome.java | 21 ++++++++++++++----- .../generator/SeedBasedWorldGenerator.java | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/core/src/main/java/mc/core/world/Biome.java b/core/src/main/java/mc/core/world/Biome.java index 71a0fad..6753ad4 100644 --- a/core/src/main/java/mc/core/world/Biome.java +++ b/core/src/main/java/mc/core/world/Biome.java @@ -25,13 +25,24 @@ public enum Biome { DESERT_HILLS(17, "Desert hills", 0xffe4b5), FOREST_HILLS(18, "Forest hills", 0x006400), TAIGA_HILLS(19, "Taiga hills", 0xf0f8ff), - EXTREME_HILLS_EDGE(20, "Extreme hills edge", 0xffffff), + EXTREME_HILLS_ED(20, "Extreme hills edge", 0xffffff), JUNGLE(21, "Jungle", 0xadff2f), JUNGLE_HILLS(22, "Jungle hills", 0xadff2f), - DEEP_OCEAN(23, "Deep ocean", 0x000080), - TUNDRA(24, "Tundra", 0xc0c0c0), - SAVANNA(25, "Savana", 0xcd8513), - SAVANNA_FOREST(26, "Savana forest", 0x8b4513); + JUNGLE_HILLS_2(23, "Jungle hills", 0xadff2f), //WTF? + DEEP_OCEAN(24, "Deep ocean", 0x000080), + STONE_BEACH(25, "Stone beach", 0xffffff), + COLD_BEACH(26, "Cold beach", 0xffffff), + BIRCH_FOREST(27, "Birch forest", 0xffffff), + BIRCH_FOREST_HILLS(28, "Birch forest hills", 0xffffff), + DARK_FOREST(29, "Dark forest", 0xffffff), + COLD_TAIGA(30, "Cold taiga", 0xffffff), + COLD_TAIGA_HILLS(31, "Cold taiga hills", 0xffffff), + MEGA_TAIGA(32, "Mega taiga", 0xffffff), + MEGA_TAIGA_HILLS(33, "Mega taiga hills", 0xffffff), + EXTREME_HILLS_PLUS(34, "Extreme hills plus", 0xffffff), + SAVANNA(35, "Savana", 0xcd8513), + SAVANNA_PLATO(36, "Savana plato", 0x8b4513), + VOID(127, "Void", 0xffffff); @Getter private final int id; diff --git a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java index f1f63de..e7ffeff 100644 --- a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java +++ b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java @@ -299,7 +299,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator { if (temperature == Temperature.FROST) { if (wetness == Wetness.DRIEST || wetness == Wetness.DRY) { - return Biome.TUNDRA; + return Biome.COLD_TAIGA; } else { if (height > HILLS_HEIGHT) { return Biome.ICE_MOUNTAINS; @@ -353,7 +353,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator { return Biome.FOREST; } } else { - return Biome.SAVANNA_FOREST; + return Biome.SAVANNA_PLATO; } } From 2c611a888d5eb106d3ccdab0300820111240962e Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Tue, 7 Aug 2018 21:33:05 +0300 Subject: [PATCH 12/15] hotfix: Oops! --- build.gradle | 1 - core/build.gradle | 2 + core/src/main/java/mc/core/Location.java | 6 ++ .../mc/core/serialization/IChunkReader.java | 2 +- core/src/main/java/mc/core/world/Region.java | 1 + core/src/main/java/mc/core/world/World.java | 2 +- .../mc/core/world/block/AbstractBlock.java | 3 + .../main/java/mc/core/world/block/Block.java | 3 + .../mc/core/world/block/BlockFactory.java | 12 ++-- .../java/mc/core/world/block/BlockType.java | 6 +- .../main/java/mc/core/world/chunk/Chunk.java | 3 +- .../java/mc/core/world/chunk/ChunkLoader.java | 2 +- .../main/java/mc/world/flat/FlatWorld.java | 11 +-- .../generated_world/chunk/ChunkImpl.java | 69 +++++++------------ .../generated_world/chunk/ChunkProxy.java | 48 ++----------- .../chunk/InMemoryCacheChunkLoader.java | 2 + .../generator/SeedBasedWorldGenerator.java | 23 ++++--- .../generated_world/region/RegionImpl.java | 2 + .../BlockSerializerDeserializer.java | 8 +-- .../serialization/ChunkReader.java | 8 +-- .../serialization/ChunkSerializer.java | 8 +-- .../generated_world/world/CubicWorld.java | 4 +- .../proto_1_12_2/packets/ChunkDataPacket.java | 14 ++-- .../netty/handlers/LoginHandler.java | 16 ++--- settings.gradle | 2 +- 25 files changed, 107 insertions(+), 151 deletions(-) diff --git a/build.gradle b/build.gradle index 13d4052..74a7f0e 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,6 @@ subprojects { /* Components */ compile (group: 'org.projectlombok', name: 'lombok', version: '1.16.16') - compile 'com.flowpowered:flow-nbt:1.0.0' //Named Binary Tags } task copyDep(type: Copy) { diff --git a/core/build.gradle b/core/build.gradle index 98cd941..0ae659a 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -14,4 +14,6 @@ dependencies { /* Components */ compile (group: 'commons-io', name: 'commons-io', version: '2.6') compile (group: 'com.google.guava', name: 'guava', version: '24.1-jre') + /* Named Binary Tags */ + compile (group: 'com.flowpowered', name: 'flow-nbt', version: '1.0.0') } diff --git a/core/src/main/java/mc/core/Location.java b/core/src/main/java/mc/core/Location.java index 7e560f3..adee609 100644 --- a/core/src/main/java/mc/core/Location.java +++ b/core/src/main/java/mc/core/Location.java @@ -35,6 +35,12 @@ public class Location implements Serializable{ set(compactValue); } + public void set(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + public void set(Location location) { this.x = location.x; this.y = location.y; diff --git a/core/src/main/java/mc/core/serialization/IChunkReader.java b/core/src/main/java/mc/core/serialization/IChunkReader.java index 0ecf126..4cb4530 100644 --- a/core/src/main/java/mc/core/serialization/IChunkReader.java +++ b/core/src/main/java/mc/core/serialization/IChunkReader.java @@ -1,6 +1,6 @@ package mc.core.serialization; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; import mc.core.world.Region; import java.io.IOException; diff --git a/core/src/main/java/mc/core/world/Region.java b/core/src/main/java/mc/core/world/Region.java index dec2730..8448422 100644 --- a/core/src/main/java/mc/core/world/Region.java +++ b/core/src/main/java/mc/core/world/Region.java @@ -2,6 +2,7 @@ package mc.core.world; import mc.core.serialization.IRegionReaderWriter; import mc.core.serialization.Serializer; +import mc.core.world.chunk.Chunk; import java.io.IOException; import java.io.Serializable; diff --git a/core/src/main/java/mc/core/world/World.java b/core/src/main/java/mc/core/world/World.java index bc18bf8..0bde5b1 100644 --- a/core/src/main/java/mc/core/world/World.java +++ b/core/src/main/java/mc/core/world/World.java @@ -4,9 +4,9 @@ */ package mc.core.world; -import mc.core.Location; import mc.core.WarpPosition; import mc.core.nbt.Taggable; +import mc.core.world.chunk.Chunk; import java.io.Serializable; import java.util.UUID; diff --git a/core/src/main/java/mc/core/world/block/AbstractBlock.java b/core/src/main/java/mc/core/world/block/AbstractBlock.java index 1e98d40..5d0572c 100644 --- a/core/src/main/java/mc/core/world/block/AbstractBlock.java +++ b/core/src/main/java/mc/core/world/block/AbstractBlock.java @@ -16,6 +16,9 @@ public abstract class AbstractBlock implements Block { @Getter private int meta; @Getter + @Setter + private int light = 0; //TODO need to know range of values + @Getter private final BlockType blockType; private final Map> nbtTagsMap = new HashMap<>(); diff --git a/core/src/main/java/mc/core/world/block/Block.java b/core/src/main/java/mc/core/world/block/Block.java index 655bf18..a140ab0 100644 --- a/core/src/main/java/mc/core/world/block/Block.java +++ b/core/src/main/java/mc/core/world/block/Block.java @@ -38,6 +38,9 @@ public interface Block extends Taggable, Serializable{ */ int getMeta(); + int getLight(); + void setLight(int light); + /** * Getting block type */ diff --git a/core/src/main/java/mc/core/world/block/BlockFactory.java b/core/src/main/java/mc/core/world/block/BlockFactory.java index 2405524..868eb52 100644 --- a/core/src/main/java/mc/core/world/block/BlockFactory.java +++ b/core/src/main/java/mc/core/world/block/BlockFactory.java @@ -4,21 +4,25 @@ import mc.core.Location; public class BlockFactory { + public Block create(BlockType blockType, int meta, int x, int y, int z) { + return new EmbeddedBlock(blockType, meta, x, y, z); + } + public Block create(BlockType blockType, int meta) { - return new EmbeddedBlock(blockType, meta); + return new EmbeddedBlock(blockType, meta, 0, 0, 0); } public Block create(BlockType blockType) { - return create(blockType, 0); + return create(blockType, 0, 0, 0, 0); } /** * For first-time generation */ private class EmbeddedBlock extends AbstractBlock { - EmbeddedBlock(BlockType type, int meta) { + EmbeddedBlock(BlockType type, int meta, int x, int y, int z) { super(type, meta); - super.setLocation(new Location(0,0,0)); + super.setLocation(new Location(x,y,z)); } } } diff --git a/core/src/main/java/mc/core/world/block/BlockType.java b/core/src/main/java/mc/core/world/block/BlockType.java index 4b4b467..7adb32a 100644 --- a/core/src/main/java/mc/core/world/block/BlockType.java +++ b/core/src/main/java/mc/core/world/block/BlockType.java @@ -1,16 +1,16 @@ -package mc.core.block; +package mc.core.world.block; import lombok.Getter; public enum BlockType { + AIR(0, "Air"), STONE(1, "Stone"), GRASS(2, "Grass"), DIRT(3, "Dirt"), BEDROCK(7, "Bedrock"), WATER(8, "Water"), SAND(12, "Sand"), - SNOW(32, "Snow"), - AIR(0, "Air"); + SNOW(32, "Snow"); @Getter private final int id; diff --git a/core/src/main/java/mc/core/world/chunk/Chunk.java b/core/src/main/java/mc/core/world/chunk/Chunk.java index c99afc3..38593d4 100644 --- a/core/src/main/java/mc/core/world/chunk/Chunk.java +++ b/core/src/main/java/mc/core/world/chunk/Chunk.java @@ -2,9 +2,10 @@ * DmitriyMX * 2018-04-15 */ -package mc.core.world; +package mc.core.world.chunk; import mc.core.Location; +import mc.core.world.Biome; import mc.core.world.block.Block; import java.io.Serializable; diff --git a/core/src/main/java/mc/core/world/chunk/ChunkLoader.java b/core/src/main/java/mc/core/world/chunk/ChunkLoader.java index a8213e4..cd0f06f 100644 --- a/core/src/main/java/mc/core/world/chunk/ChunkLoader.java +++ b/core/src/main/java/mc/core/world/chunk/ChunkLoader.java @@ -1,4 +1,4 @@ -package mc.core.world; +package mc.core.world.chunk; import java.util.Optional; diff --git a/flat_world/src/main/java/mc/world/flat/FlatWorld.java b/flat_world/src/main/java/mc/world/flat/FlatWorld.java index 4f7ef22..8813b51 100644 --- a/flat_world/src/main/java/mc/world/flat/FlatWorld.java +++ b/flat_world/src/main/java/mc/world/flat/FlatWorld.java @@ -11,21 +11,24 @@ import mc.core.Location; import mc.core.WarpPosition; import mc.core.player.Look; import mc.core.world.*; +import mc.core.world.chunk.Chunk; import java.util.UUID; import java.util.stream.Stream; public class FlatWorld implements World { - @Getter@Setter + @Getter + @Setter private UUID worldId = UUID.fromString("00000000-0000-0000-C000-000000000046"); - @Getter@Setter + @Getter + @Setter private String name; @Getter @Setter private WarpPosition spawn = new WarpPosition(new Location(0, 6, 0), new Look(0, 0)); - private Chunk chunk = new SimpleChunk(); + private Chunk chunk = new SimpleChunk(0, 0, 0); //FIXME temporary dummy @Override public IWorldType getWorldType() { @@ -49,7 +52,7 @@ public class FlatWorld implements World { @Override public void setRegion(int x, int z, Region region) { - + throw new UnsupportedOperationException(); } @Override diff --git a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java index 464b980..f2cd8fd 100644 --- a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java +++ b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkImpl.java @@ -2,16 +2,18 @@ package mc.world.generated_world.chunk; import lombok.Getter; import lombok.RequiredArgsConstructor; -import mc.core.block.Block; -import mc.core.block.BlockType; +import mc.core.world.block.Block; +import mc.core.world.block.BlockFactory; +import mc.core.world.block.BlockType; import mc.core.world.Biome; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; import mc.core.world.Region; import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE; @RequiredArgsConstructor public class ChunkImpl implements Chunk{ + private static final BlockFactory blockFactory = new BlockFactory(); @Getter private final int x; @Getter @@ -22,33 +24,25 @@ public class ChunkImpl implements Chunk{ private final transient Region region; @Override - public int getBlockType(int x, int y, int z) { - return blocks[x][y][z].getId(); + public Block getBlock(int x, int y, int z) { + Block block = blocks[x][y][z]; + if (block == null) { + block = blockFactory.create(BlockType.AIR, 0, x, y, z); + } + block.setLight(15); + return block; } @Override - public void setBlockType(int x, int y, int z, int type) { - - } - - @Override - public int getBlockMetadata(int x, int y, int z) { - return 0; - } - - @Override - public void setBlockMetadata(int x, int y, int z, int metadata) { - - } - - @Override - public int getBlockLight(int x, int y, int z) { - return 15; - } - - @Override - public void setBlockLight(int x, int y, int z, int lightLevel) { - + public void setBlock(Block block) { + if (block.getBlockType() == BlockType.AIR) { + blocks[block.getLocation().getBlockX()] + [block.getLocation().getBlockY()] + [block.getLocation().getBlockZ()] = null; + } + blocks[block.getLocation().getBlockX()] + [block.getLocation().getBlockY()] + [block.getLocation().getBlockZ()] = block; } @Override @@ -58,7 +52,7 @@ public class ChunkImpl implements Chunk{ @Override public void setSkyLight(int x, int y, int z, int lightLevel) { - + throw new UnsupportedOperationException(); } @Override @@ -68,7 +62,7 @@ public class ChunkImpl implements Chunk{ @Override public void setAddition(int x, int y, int z, int value) { - + throw new UnsupportedOperationException(); } @Override @@ -80,21 +74,4 @@ public class ChunkImpl implements Chunk{ public void setBiome(int x, int z, Biome biome) { region.setBiome(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE, biome); } - - @Override - public void setBlock(int x, int y, int z, Block block) { - if (block.getBlockType() == BlockType.AIR) { - blocks[x][y][z] = null; - } - blocks[x][y][z] = block; - } - - @Override - public Block getBlock(int x, int y, int z) { - Block block = blocks[x][y][z]; - if (block == null) { - return Block.airBlock(x, y, z); - } - return blocks[x][y][z]; - } } diff --git a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java index 4490001..12e628e 100644 --- a/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java +++ b/generated_world/src/main/java/mc/world/generated_world/chunk/ChunkProxy.java @@ -1,8 +1,8 @@ package mc.world.generated_world.chunk; -import mc.core.block.Block; +import mc.core.world.block.Block; import mc.core.world.Biome; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; @@ -29,39 +29,15 @@ public class ChunkProxy implements Chunk { } @Override - public int getBlockType(int x, int y, int z) { + public Block getBlock(int x, int y, int z) { use(); - return chunk.getBlockType(x, y, z); + return chunk.getBlock(x, y, z); } @Override - public void setBlockType(int x, int y, int z, int type) { + public void setBlock(Block block) { use(); - chunk.setBlockType(x, y, z, type); - } - - @Override - public int getBlockMetadata(int x, int y, int z) { - use(); - return chunk.getBlockMetadata(x, y, z); - } - - @Override - public void setBlockMetadata(int x, int y, int z, int metadata) { - use(); - chunk.setBlockMetadata(x, y, z, metadata); - } - - @Override - public int getBlockLight(int x, int y, int z) { - use(); - return chunk.getBlockLight(x, y, z); - } - - @Override - public void setBlockLight(int x, int y, int z, int lightLevel) { - use(); - chunk.setBlockLight(x, y, z, lightLevel); + chunk.setBlock(block); } @Override @@ -117,16 +93,4 @@ public class ChunkProxy implements Chunk { use(); return chunk.getZ(); } - - @Override - public void setBlock(int x, int y, int z, Block block) { - use(); - chunk.setBlock(x, y, z, block); - } - - @Override - public Block getBlock(int x, int y, int z) { - use(); - return chunk.getBlock(x, y, z); - } } diff --git a/generated_world/src/main/java/mc/world/generated_world/chunk/InMemoryCacheChunkLoader.java b/generated_world/src/main/java/mc/world/generated_world/chunk/InMemoryCacheChunkLoader.java index 2724497..c499d7f 100644 --- a/generated_world/src/main/java/mc/world/generated_world/chunk/InMemoryCacheChunkLoader.java +++ b/generated_world/src/main/java/mc/world/generated_world/chunk/InMemoryCacheChunkLoader.java @@ -3,6 +3,8 @@ package mc.world.generated_world.chunk; import lombok.extern.slf4j.Slf4j; import mc.core.serialization.Serializer; import mc.core.world.*; +import mc.core.world.chunk.Chunk; +import mc.core.world.chunk.ChunkLoader; import mc.world.generated_world.serialization.ChunkReader; import mc.world.generated_world.serialization.RegionReaderWriter; import org.springframework.beans.factory.annotation.Autowired; diff --git a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java index 8253165..8b8ce2d 100644 --- a/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java +++ b/generated_world/src/main/java/mc/world/generated_world/generator/SeedBasedWorldGenerator.java @@ -2,9 +2,10 @@ package mc.world.generated_world.generator; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import mc.core.block.BlockFactory; -import mc.core.block.BlockType; +import mc.core.world.block.BlockFactory; +import mc.core.world.block.BlockType; import mc.core.world.*; +import mc.core.world.chunk.Chunk; import mc.world.generated_world.region.RegionImpl; import mc.world.generated_world.serialization.ChunkSerializer; import mc.world.generated_world.serialization.RegionReaderWriter; @@ -308,35 +309,35 @@ public class SeedBasedWorldGenerator implements WorldGenerator { for (int y = 0; y < WORLD_SEA_LEVEL; y ++) { Chunk chunk = region.getChunkAt(x / 16, y / 16, z / 16); if (y == 0) { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.BEDROCK, 0)); + chunk.setBlock(blockFactory.create(BlockType.BEDROCK, 0, x % 16, y % 16, z % 16)); continue; } if (y < heightMap[x][z]) { if (y < heightMap[x][z] - grassMap[x][z]) { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.STONE, 0)); + chunk.setBlock(blockFactory.create(BlockType.STONE, 0, x % 16, y % 16, z % 16)); } else { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.SAND, 0)); + chunk.setBlock(blockFactory.create(BlockType.SAND, 0, x % 16, y % 16, z % 16)); } } else { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.WATER, 0)); + chunk.setBlock(blockFactory.create(BlockType.WATER, 0, x % 16, y % 16, z % 16)); } } } else { for (int y = 0; y < heightMap[x][z]; y++) { Chunk chunk = region.getChunkAt(x / 16, y / 16, z / 16); if (y == 0) { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.BEDROCK, 0)); + chunk.setBlock(blockFactory.create(BlockType.BEDROCK, 0, x % 16, y % 16, z % 16)); continue; } if (y < heightMap[x][z] - grassMap[x][z]) { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.STONE, 0)); + chunk.setBlock(blockFactory.create(BlockType.STONE, 0, x % 16, y % 16, z % 16)); } else { if (biomes[x][z] == Biome.DESERT || biomes[x][z] == Biome.DESERT_HILLS) { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.SAND, 0)); + chunk.setBlock(blockFactory.create(BlockType.SAND, 0, x % 16, y % 16, z % 16)); } else if (biomes[x][z] == Biome.TAIGA || biomes[x][z] == Biome.TAIGA_HILLS) { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.DIRT, 0)); + chunk.setBlock(blockFactory.create(BlockType.DIRT, 0, x % 16, y % 16, z % 16)); } else { - chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.GRASS, 0)); + chunk.setBlock(blockFactory.create(BlockType.GRASS, 0, x % 16, y % 16, z % 16)); } } } diff --git a/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java b/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java index 812512f..83cb6c6 100644 --- a/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java +++ b/generated_world/src/main/java/mc/world/generated_world/region/RegionImpl.java @@ -6,6 +6,8 @@ import lombok.extern.slf4j.Slf4j; import mc.core.serialization.IRegionReaderWriter; import mc.core.serialization.Serializer; import mc.core.world.*; +import mc.core.world.chunk.Chunk; +import mc.core.world.chunk.ChunkLoader; import mc.world.generated_world.chunk.InMemoryCacheChunkLoader; import mc.world.generated_world.chunk.ChunkImpl; import mc.world.generated_world.chunk.ChunkProxy; diff --git a/generated_world/src/main/java/mc/world/generated_world/serialization/BlockSerializerDeserializer.java b/generated_world/src/main/java/mc/world/generated_world/serialization/BlockSerializerDeserializer.java index a176afe..3863fb0 100644 --- a/generated_world/src/main/java/mc/world/generated_world/serialization/BlockSerializerDeserializer.java +++ b/generated_world/src/main/java/mc/world/generated_world/serialization/BlockSerializerDeserializer.java @@ -1,11 +1,11 @@ package mc.world.generated_world.serialization; -import mc.core.block.Block; -import mc.core.block.BlockFactory; -import mc.core.block.BlockType; +import mc.core.world.block.Block; +import mc.core.world.block.BlockFactory; +import mc.core.world.block.BlockType; import mc.core.serialization.Deserializer; import mc.core.serialization.Serializer; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; /** * Prototype diff --git a/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkReader.java b/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkReader.java index 8b77dde..5e7c419 100644 --- a/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkReader.java +++ b/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkReader.java @@ -1,10 +1,9 @@ package mc.world.generated_world.serialization; -import mc.core.Location; -import mc.core.block.Block; +import mc.core.world.block.Block; import mc.core.serialization.Deserializer; import mc.core.serialization.IChunkReader; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; import mc.core.world.Region; import mc.world.generated_world.chunk.ChunkImpl; import org.springframework.beans.factory.annotation.Autowired; @@ -41,8 +40,7 @@ public class ChunkReader implements IChunkReader{ blockBytes[1] = chunkBytes[1 + 3 * i]; blockBytes[2] = chunkBytes[2 + 3 * i]; Block block = blockDeserializer.deserialize(blockBytes); - Location blockLocation = block.getLocation(); - chunk.setBlock(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ(), block); + chunk.setBlock(block); } return chunk; } diff --git a/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkSerializer.java b/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkSerializer.java index aae910b..cba4572 100644 --- a/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkSerializer.java +++ b/generated_world/src/main/java/mc/world/generated_world/serialization/ChunkSerializer.java @@ -1,11 +1,11 @@ package mc.world.generated_world.serialization; import lombok.extern.slf4j.Slf4j; -import mc.core.block.Block; -import mc.core.block.BlockFactory; -import mc.core.block.BlockType; +import mc.core.world.block.Block; +import mc.core.world.block.BlockFactory; +import mc.core.world.block.BlockType; import mc.core.serialization.Serializer; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; import org.springframework.beans.factory.annotation.Autowired; import java.io.ByteArrayOutputStream; diff --git a/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java b/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java index 6c39781..d7f1724 100644 --- a/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java +++ b/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java @@ -6,9 +6,9 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; import mc.core.Location; import mc.core.WarpPosition; -import mc.core.block.BlockType; +import mc.core.world.block.BlockType; import mc.core.player.Look; -import mc.core.world.Chunk; +import mc.core.world.chunk.Chunk; import mc.core.world.IWorldType; import mc.core.world.Region; import mc.core.world.World; diff --git a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java index aecbbc6..122ff39 100644 --- a/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java +++ b/proto_1.12.2/src/main/java/mc/core/network/proto_1_12_2/packets/ChunkDataPacket.java @@ -8,14 +8,12 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.extern.slf4j.Slf4j; -import mc.core.Location; import mc.core.network.NetOutputStream; import mc.core.network.SCPacket; import mc.core.network.proto_1_12_2.ByteArrayOutputNetStream; -import mc.core.world.Block; -import mc.core.world.Chunk; +import mc.core.world.block.Block; +import mc.core.world.chunk.Chunk; -import java.io.*; import java.util.ArrayList; import java.util.List; @@ -80,8 +78,8 @@ public class ChunkDataPacket implements SCPacket { @Getter private List chunks = new ArrayList<>(); - private int serializeBlockState(int id, int state) { - return (id << 4) | state; + private int serializeBlockState(int id, int meta) { + return (id << 4) | meta; } @Override @@ -115,7 +113,7 @@ public class ChunkDataPacket implements SCPacket { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { Block block = chunk.getBlock(x, y, z); - int blockState = serializeBlockState(block.getId(), block.getState()); + int blockState = serializeBlockState(block.getId(), block.getMeta()); int currentIndexPaletteBlock; if (!palette.contains(blockState)) { @@ -151,7 +149,7 @@ public class ChunkDataPacket implements SCPacket { } if (!biomeFinally) { - biomes.writeByte(chunk.getBiome(x, z)); + biomes.writeByte(chunk.getBiome(x, z).getId()); if (x == 15 && z == 15) { biomeFinally = true; } diff --git a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java index a0c9591..efc67d3 100644 --- a/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java +++ b/proto_1.12.2_netty/src/main/java/mc/core/network/proto_1_12_2/netty/handlers/LoginHandler.java @@ -48,7 +48,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand Player player = playerManager.getPlayer(packet.getPlayerName()) .orElseGet(() -> playerManager.createPlayer( packet.getPlayerName(), - world.getSpawn(), + world.getSpawn().getLocation(), new Look(0f, 0f))); channel.writeAndFlush(new LoginSuccessPacket( @@ -68,7 +68,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand // Spawn Position SpawnPositionPacket pkt2 = new SpawnPositionPacket(); - pkt2.setLocation(world.getSpawn()); + pkt2.setLocation(world.getSpawn().getLocation()); channel.write(pkt2); // Player Abilities @@ -80,22 +80,14 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand channel.write(pkt3); channel.flush(); - // Send chunk data + // One Chunk ChunkDataPacket pkt8 = new ChunkDataPacket(); pkt8.setX(0); pkt8.setZ(0); - pkt8.getChunks().add(world.getChunk(0,0)); + pkt8.getChunks().add(world.getChunk(0, 0,0)); pkt8.setInitChunk(true); channel.writeAndFlush(pkt8); - // One Chunk - ChunkDataPacket pkt9 = new ChunkDataPacket(); - pkt9.setInitChunk(true); - pkt9.setX(0); - pkt9.setZ(0); - pkt9.getChunks().add(world.getChunk(0, 0)); - channel.writeAndFlush(pkt9); - // Player Position And Look PlayerPositionAndLookPacket pkt4 = new PlayerPositionAndLookPacket(); pkt4.setLocation(player.getLocation()); diff --git a/settings.gradle b/settings.gradle index 7855426..b865638 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,5 +5,5 @@ include('flat_world') include('vanilla_commands') include('proto_1.12.2') // Protocol 1.12.2 include('proto_1.12.2_netty') // Protocol 1.12.2 (Netty impl.) -include 'generated_world' +include('generated_world') From f51dba79a687082b85f5b4620dedd5c8b782ef47 Mon Sep 17 00:00:00 2001 From: Forwolk Date: Wed, 8 Aug 2018 00:17:07 +0300 Subject: [PATCH 13/15] Region managed moved to CubicWorld --- .../generated_world/world/CubicWorld.java | 148 +++++++++++++++--- .../generated_world/world/RegionManager.java | 143 ----------------- .../SeedRandomGeneratorTest.java | 2 + 3 files changed, 124 insertions(+), 169 deletions(-) delete mode 100644 generated_world/src/main/java/mc/world/generated_world/world/RegionManager.java diff --git a/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java b/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java index d7f1724..85c3290 100644 --- a/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java +++ b/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java @@ -4,34 +4,65 @@ import com.flowpowered.nbt.Tag; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import mc.core.Direction; import mc.core.Location; import mc.core.WarpPosition; -import mc.core.world.block.BlockType; import mc.core.player.Look; -import mc.core.world.chunk.Chunk; import mc.core.world.IWorldType; import mc.core.world.Region; import mc.core.world.World; +import mc.core.world.WorldGenerator; +import mc.core.world.block.BlockType; +import mc.core.world.chunk.Chunk; +import mc.world.generated_world.serialization.RegionReaderWriter; import org.springframework.beans.factory.annotation.Autowired; +import java.io.File; +import java.io.IOException; +import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import java.util.UUID; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Stream; -import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE; -import static mc.world.generated_world.WorldConstants.WORLD_MAX_HEIGHT; +import static mc.world.generated_world.WorldConstants.*; + +/* + * NORTH + * + * EAST WEST + * + * SOUTH + * + * + ----> X + * | + * | + * | + * V Z + */ @Slf4j public class CubicWorld implements World { + private int pointX = -1; + private int pointZ = -1; + private int sizeX = 2; + private int sizeZ = 2; + private Region[][] regions = new Region[sizeX][sizeZ]; + private final Lock regionSaveLock = new ReentrantLock(); + @Autowired + private RegionReaderWriter regionReaderWriter; + @Autowired + private WorldGenerator worldGenerator; + @Setter + private boolean autoSaveRegionAfterGenerating = true; @Getter private final UUID worldId; private final int seed; private volatile WarpPosition warpPosition; private final transient Object spawnLocationLock = new Object(); private final Map> nbtTagMap = new HashMap<>(); - @Autowired - private RegionManager regionManager; @Getter@Setter private String name; @@ -62,23 +93,8 @@ public class CubicWorld implements World { @Override public WarpPosition getSpawn() { - if (warpPosition == null) { - synchronized (spawnLocationLock) { - if (warpPosition == null) { - log.warn("Spawn location is not defined. Trying to select best location"); - warpPosition = new WarpPosition(Location.startPointLocation(), new Look(0, 0)); - for (int y = WORLD_MAX_HEIGHT; y > 0; y --) { - Chunk chunk = getChunk(0,y / WORLD_CHUNK_SIZE, 0); - if (chunk.getBlock(0, y, 0).getBlockType() != BlockType.AIR) { - warpPosition = new WarpPosition(new Location(0, y + 1, 0), new Look(0, 0)); - break; - } - } - warpPosition = new WarpPosition(Location.startPointLocation(), new Look(0,0)); - } - } - } - return warpPosition; + /* FIXME */ + return new WarpPosition(new Location(0, 100, 0), new Look(0, 0)); } @Override @@ -90,7 +106,8 @@ public class CubicWorld implements World { @Override public Chunk getChunk(int x, int y, int z) { - return null; + Region region = getRegion(x / 16, z / 16); + return region.getChunkAt(x % 16, y % 16, z % 16); } @Override @@ -100,12 +117,42 @@ public class CubicWorld implements World { @Override public Region getRegion(int x, int z) { - return null; + checkCoordsInCache(x, z); + Region region; + if (regions[x - pointX][z - pointZ] == null) { + File file = new File(new File("worlds", this.getWorldId().toString()), MessageFormat.format(REGION_FILE_NAME_TEMPLATE, x, z)); + if (!file.exists()) { + region = worldGenerator.generateRegion(x, z, this); + if (autoSaveRegionAfterGenerating) { + try { + regionReaderWriter.write(region); + } catch (IOException e) { + log.error("Error occurred while saving region data"); + } + } + } else { + try { + region = regionReaderWriter.read(x, z, this); + } catch (IOException e) { + log.error("Error occurred while loading region"); + region = null; + } + } + setRegion(region.getX(), region.getZ(), region); + } else { + region = regions[x - pointX][z - pointZ]; + } + return region; } @Override public void setRegion(int x, int z, Region region) { - + try { + regionSaveLock.lock(); + regions[x - pointX][z - pointZ] = region; + } finally { + regionSaveLock.unlock(); + } } @Override @@ -127,4 +174,53 @@ public class CubicWorld implements World { public Stream> tagStream() { return nbtTagMap.values().stream(); } + + private void checkCoordsInCache (int x, int z) { + if (x < pointX) { + addLines(Direction.EAST, pointX - x); + } else if (x > pointX + sizeX) { + addLines(Direction.WEST, x - (pointX + sizeX)); + } else if (z < pointZ) { + addLines(Direction.NORTH, pointZ - z); + } else if (z > pointZ + sizeZ) { + addLines(Direction.SOUTH, z - (pointZ + sizeZ)); + } + } + + private void addLines (Direction direction, int amount) { + int addBeforeX = 0; + int addAfterX = 0; + int addBeforeZ = 0; + int addAfterZ = 0; + switch (direction) { + case NORTH: + addBeforeZ = amount; + break; + case EAST: + addBeforeX = amount; + break; + case WEST: + addAfterX = amount; + break; + case SOUTH: + addAfterZ = amount; + break; + } + try { + regionSaveLock.lock(); + int tempSizeX = sizeX + addAfterX + addBeforeX; + int tempSizeZ = sizeZ + addAfterZ + addBeforeZ; + Region[][] temp = new Region[tempSizeX][tempSizeZ]; + for (int x = 0; x < sizeX; x ++) { + System.arraycopy(regions[x], 0, temp[x + addBeforeX], addBeforeZ, sizeZ); + } + + this.sizeX = tempSizeX; + this.sizeZ = tempSizeZ; + this.pointX = pointX - addBeforeX; + this.pointZ = pointZ - addBeforeZ; + } finally { + regionSaveLock.unlock(); + } + } } diff --git a/generated_world/src/main/java/mc/world/generated_world/world/RegionManager.java b/generated_world/src/main/java/mc/world/generated_world/world/RegionManager.java deleted file mode 100644 index 0cc0ef4..0000000 --- a/generated_world/src/main/java/mc/world/generated_world/world/RegionManager.java +++ /dev/null @@ -1,143 +0,0 @@ -package mc.world.generated_world.world; - -import lombok.Setter; -import lombok.extern.slf4j.Slf4j; -import mc.core.Direction; -import mc.core.world.Region; -import mc.core.world.World; -import mc.core.world.WorldGenerator; -import mc.world.generated_world.serialization.RegionReaderWriter; -import org.springframework.beans.factory.annotation.Autowired; - -import java.io.File; -import java.io.IOException; -import java.text.MessageFormat; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static mc.world.generated_world.WorldConstants.REGION_FILE_NAME_TEMPLATE; - -/* -* NORTH -* -* EAST WEST -* -* SOUTH -* -* + ----> X -* | -* | -* | -* V Z -*/ -@Slf4j -public class RegionManager { - private final World world; - private int pointX = -1; - private int pointZ = -1; - private int sizeX = 2; - private int sizeZ = 2; - private Region[][] regions = new Region[sizeX][sizeZ]; - private final Lock regionSaveLock = new ReentrantLock(); - @Autowired - private RegionReaderWriter regionReaderWriter; - @Autowired - private WorldGenerator worldGenerator; - @Setter - private boolean autoSaveRegionAfterGenerating = true; - - - public RegionManager(World world) { - this.world = world; - } - - public void setRegion (Region region) { - int x = region.getX(); - int z = region.getZ(); - - try { - regionSaveLock.lock(); - regions[x - pointX][z - pointZ] = region; - } finally { - regionSaveLock.unlock(); - } - } - - private void checkCoordsInCache (int x, int z) { - if (x < pointX) { - addLines(Direction.EAST, pointX - x); - } else if (x > pointX + sizeX) { - addLines(Direction.WEST, x - (pointX + sizeX)); - } else if (z < pointZ) { - addLines(Direction.NORTH, pointZ - z); - } else if (z > pointZ + sizeZ) { - addLines(Direction.SOUTH, z - (pointZ + sizeZ)); - } - } - - public Region getRegion (int x, int z) { - checkCoordsInCache(x, z); - Region region; - if (regions[x - pointX][z - pointZ] == null) { - File file = new File(new File("worlds", world.getWorldId().toString()), MessageFormat.format(REGION_FILE_NAME_TEMPLATE, x, z)); - if (!file.exists()) { - region = worldGenerator.generateRegion(x, z, world); - if (autoSaveRegionAfterGenerating) { - try { - regionReaderWriter.write(region); - } catch (IOException e) { - log.error("Error occurred while saving region data"); - } - } - } else { - try { - region = regionReaderWriter.read(x, z, world); - } catch (IOException e) { - log.error("Error occurred while loading region"); - region = null; - } - } - setRegion(region); - } else { - region = regions[x - pointX][z - pointZ]; - } - return region; - } - - private void addLines (Direction direction, int amount) { - int addBeforeX = 0; - int addAfterX = 0; - int addBeforeZ = 0; - int addAfterZ = 0; - switch (direction) { - case NORTH: - addBeforeZ = amount; - break; - case EAST: - addBeforeX = amount; - break; - case WEST: - addAfterX = amount; - break; - case SOUTH: - addAfterZ = amount; - break; - } - try { - int tempSizeX = sizeX + addAfterX + addBeforeX; - int tempSizeZ = sizeZ + addAfterZ + addBeforeZ; - Region[][] temp = new Region[tempSizeX][tempSizeZ]; - for (int x = 0; x < sizeX; x ++) { - System.arraycopy(regions[x], 0, temp[x + addBeforeX], addBeforeZ, sizeZ); - } - - this.sizeX = tempSizeX; - this.sizeZ = tempSizeZ; - this.pointX = pointX - addBeforeX; - this.pointZ = pointZ - addBeforeZ; - } finally { - regionSaveLock.unlock(); - } - } - -} diff --git a/generated_world/src/test/java/mc/world/generated_world/SeedRandomGeneratorTest.java b/generated_world/src/test/java/mc/world/generated_world/SeedRandomGeneratorTest.java index a99a251..6c5fbe4 100644 --- a/generated_world/src/test/java/mc/world/generated_world/SeedRandomGeneratorTest.java +++ b/generated_world/src/test/java/mc/world/generated_world/SeedRandomGeneratorTest.java @@ -1,6 +1,7 @@ package mc.world.generated_world; import mc.world.generated_world.generator.SeedRandomGenerator; +import org.junit.Ignore; import org.junit.Test; import javax.imageio.ImageIO; @@ -9,6 +10,7 @@ import java.io.File; import static org.junit.Assert.*; +@Ignore public class SeedRandomGeneratorTest { @Test From 5db14851eee3b825a3ee820f278e0f87ba8d4d6c Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Wed, 8 Aug 2018 01:37:46 +0300 Subject: [PATCH 14/15] fix: gradle run application Example: gradle runApp -PworkDir="D:\mc-core" --- build.gradle | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 74a7f0e..f7f6e99 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -subprojects { +allprojects { apply plugin: 'java' compileJava { @@ -10,7 +10,9 @@ subprojects { repositories { mavenCentral() } +} +subprojects { ext { slf4j_version = '1.7.21' spring_version = '4.2.5.RELEASE' @@ -44,3 +46,23 @@ subprojects { delete 'libs' } } + +task runApp(type: JavaExec) { + main = 'mc.core.Main' + + workingDir = (project.hasProperty("workDir") ? project.workDir : '.') + + subprojects.findAll().each{ prj -> + classpath += prj.sourceSets.main.runtimeClasspath + } + /* Uncomment, if your Log Implements are folder '{workDir}/log-impl' */ + //classpath += files(fileTree(dir: new File(workingDir, "log-impl"))) + + /* Uncomment, if you used VM args */ + //jvmArgs = [ + // "-DspringConfig=app.xml", + // "-Dlog4j.configurationFile=log4j2.xml" + //] + + ignoreExitValue = true +} From 436ed620ad593bea5045f7ea4a0397d9851d288f Mon Sep 17 00:00:00 2001 From: Forwolk Date: Thu, 9 Aug 2018 22:33:47 +0300 Subject: [PATCH 15/15] fix: getChunk --- .../main/java/mc/world/generated_world/world/CubicWorld.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java b/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java index bbaff53..1ae64b7 100644 --- a/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java +++ b/generated_world/src/main/java/mc/world/generated_world/world/CubicWorld.java @@ -107,7 +107,8 @@ public class CubicWorld implements World { @Override public ChunkSection getChunk(int x, int y, int z) { - return null; + Region region = getRegion(x / 16, z / 16); + return region.getChunkAt(x % 16, y % 16, z % 16); } @Override