diff --git a/src/main/java/fr/themode/demo/PlayerInit.java b/src/main/java/fr/themode/demo/PlayerInit.java index 0ec6fe551..673fd8772 100644 --- a/src/main/java/fr/themode/demo/PlayerInit.java +++ b/src/main/java/fr/themode/demo/PlayerInit.java @@ -62,6 +62,10 @@ public class PlayerInit { netherTest.enableAutoChunkLoad(true); netherTest.setChunkGenerator(noiseTestGenerator); + InstanceContainer end = MinecraftServer.getInstanceManager().createInstanceContainer(Dimension.END); + end.enableAutoChunkLoad(true); + end.setChunkGenerator(noiseTestGenerator); + // Load some chunks beforehand int loopStart = -2; int loopEnd = 10; @@ -69,6 +73,7 @@ public class PlayerInit { for (int z = loopStart; z < loopEnd; z++) { instanceContainer.loadChunk(x, z); //netherTest.loadChunk(x, z); + end.loadChunk(x, z); } diff --git a/src/main/java/fr/themode/demo/commands/DimensionCommand.java b/src/main/java/fr/themode/demo/commands/DimensionCommand.java index 188e063ec..ec179c58a 100644 --- a/src/main/java/fr/themode/demo/commands/DimensionCommand.java +++ b/src/main/java/fr/themode/demo/commands/DimensionCommand.java @@ -30,7 +30,7 @@ public class DimensionCommand implements CommandProcessor { Instance instance = player.getInstance(); Dimension targetDimension = Dimension.NETHER; - if (instance.getDimension() == Dimension.NETHER) { + if (instance.getDimension() == targetDimension) { targetDimension = Dimension.OVERWORLD; } diff --git a/src/main/java/net/minestom/server/network/packet/server/login/JoinGamePacket.java b/src/main/java/net/minestom/server/network/packet/server/login/JoinGamePacket.java index 3183e6a76..bdad708d0 100644 --- a/src/main/java/net/minestom/server/network/packet/server/login/JoinGamePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/login/JoinGamePacket.java @@ -38,31 +38,17 @@ public class JoinGamePacket implements ServerPacket { //array of worlds writer.writeVarInt(1); - writer.writeSizedString(identifier); - // TODO: modifiable - NBTCompound dimension = new NBTCompound() - .setString("name", "test:normal") - .setFloat("ambient_light", 1F) - .setString("infiniburn", "") - .setByte("natural", (byte) 0x01) - .setByte("has_ceiling", (byte) 0x01) - .setByte("has_skylight", (byte) 0x01) - .setByte("shrunk", (byte) 0x00) - .setByte("ultrawarm", (byte) 0x00) - .setByte("has_raids", (byte) 0x00) - .setByte("respawn_anchor_works", (byte) 0x00) - .setByte("bed_works", (byte) 0x01) - .setByte("piglin_safe", (byte) 0x01) - .setInt("logical_height", 255) - ; + writer.writeSizedString("test:spawn_name"); + NBTList dimensionList = new NBTList<>(NBTTypes.TAG_Compound); - dimensionList.add(dimension); + // TODO: custom list + dimensionList.add(Dimension.OVERWORLD.toNBT()); + dimensionList.add(Dimension.NETHER.toNBT()); + dimensionList.add(Dimension.END.toNBT()); writer.writeNBT("", new NBTCompound().set("dimension", dimensionList)); - - //writer.writeInt(dimension.getId()); - writer.writeSizedString("test:normal"); - writer.writeSizedString(identifier); + writer.writeSizedString(dimension.getName().toString()); + writer.writeSizedString(identifier+"_"+dimension.getName().getPath()); writer.writeLong(hashedSeed); writer.writeByte(maxPlayers); writer.writeVarInt(viewDistance); @@ -71,7 +57,7 @@ public class JoinGamePacket implements ServerPacket { //debug writer.writeBoolean(false); //is flat - writer.writeBoolean(true); + writer.writeBoolean(levelType == LevelType.FLAT); } @Override diff --git a/src/main/java/net/minestom/server/network/packet/server/play/RespawnPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/RespawnPacket.java index 8e5241a9d..479897b18 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/RespawnPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/RespawnPacket.java @@ -17,8 +17,11 @@ public class RespawnPacket implements ServerPacket { @Override public void write(PacketWriter writer) { //TODO add api - writer.writeSizedString("test:normal"); - writer.writeSizedString("test:spawn"); + writer.writeSizedString(dimension.getName().toString()); + + // Warning: must be different for each dimension type! Otherwise the client seems to cache the world name + writer.writeSizedString("test:spawn_"+dimension.getName().getPath()); // TODO: replace by instance name? + writer.writeLong(hashedSeed); writer.writeByte(gameMode.getId()); writer.writeByte(gameMode.getId()); // Hardcore flag not included diff --git a/src/main/java/net/minestom/server/world/Dimension.java b/src/main/java/net/minestom/server/world/Dimension.java index 74bb07fba..d9c78ec06 100644 --- a/src/main/java/net/minestom/server/world/Dimension.java +++ b/src/main/java/net/minestom/server/world/Dimension.java @@ -1,16 +1,110 @@ package net.minestom.server.world; -public enum Dimension { +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import net.minestom.server.utils.NamespaceID; +import org.jglrxavpok.hephaistos.nbt.NBTCompound; - NETHER(-1), OVERWORLD(0), END(1); +import java.util.Optional; - private int id; +/** + * https://minecraft.gamepedia.com/Custom_dimension + */ +@Data +@Builder(builderMethodName = "hiddenBuilder", access = AccessLevel.PRIVATE) +public class Dimension { - Dimension(int id) { - this.id = id; + public static final Dimension OVERWORLD = Dimension.builder(NamespaceID.from("minecraft:overworld")) + .ultrawarm(false) + .natural(true) + .shrunk(false) + .piglinSafe(false) + .respawnAnchorSafe(false) + .bedSafe(true) + .raidCapable(true) + .skylightEnabled(true) + .ceilingEnabled(false) + .fixedTime(Optional.empty()) + .ambientLight(0.0f) + .logicalHeight(256) + .infiniburn(NamespaceID.from("minecraft:infiniburn_overworld")) + .build(); + + public static final Dimension NETHER = Dimension.builder(NamespaceID.from("minecraft:the_nether")) + .ultrawarm(true) + .natural(false) + .shrunk(true) + .piglinSafe(true) + .respawnAnchorSafe(true) + .bedSafe(false) + .raidCapable(false) + .skylightEnabled(false) + .ceilingEnabled(true) + .fixedTime(Optional.of(18000L)) + .ambientLight(0.1f) + .logicalHeight(128) + .infiniburn(NamespaceID.from("minecraft:infiniburn_nether")) + .build(); + + public static final Dimension END = Dimension.builder(NamespaceID.from("minecraft:the_end")) + .ultrawarm(false) + .natural(false) + .shrunk(false) + .piglinSafe(false) + .respawnAnchorSafe(false) + .bedSafe(false) + .raidCapable(true) + .skylightEnabled(false) + .ceilingEnabled(false) + .fixedTime(Optional.of(6000L)) + .ambientLight(0.0f) + .logicalHeight(256) + .infiniburn(NamespaceID.from("minecraft:infiniburn_end")) + .build(); + + private final NamespaceID name; + private final boolean natural; + private final float ambientLight; + private final boolean ceilingEnabled; + private final boolean skylightEnabled; + @Builder.Default private final Optional fixedTime = Optional.empty(); + private final boolean shrunk; + private final boolean raidCapable; + private final boolean respawnAnchorSafe; + private final boolean ultrawarm; + @Builder.Default private final boolean bedSafe = true; + private final boolean piglinSafe; + @Builder.Default private final int logicalHeight = 256; + @Builder.Default private final NamespaceID infiniburn = NamespaceID.from("minecraft:infiniburn_overworld"); + + public NBTCompound toNBT() { + NBTCompound nbt = new NBTCompound() + .setString("name", name.toString()) + .setFloat("ambient_light", ambientLight) + .setString("infiniburn", infiniburn.toString()) + .setByte("natural", (byte) (natural ? 0x01 : 0x00)) + .setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00)) + .setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00)) + .setByte("shrunk", (byte) (shrunk ? 0x01 : 0x00)) + .setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00)) + .setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00)) + .setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00)) + .setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00)) + .setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00)) + .setInt("logical_height", logicalHeight) + ; + fixedTime.ifPresent(time -> nbt.setLong("fixed_time", time)); + return nbt; } - public int getId() { - return id; + @Override + public String toString() { + return name.toString(); } + + public static DimensionBuilder builder(NamespaceID name) { + return hiddenBuilder().name(name); + } + }