From 8da830503a931a189c38145a25a33cc89eac7006 Mon Sep 17 00:00:00 2001 From: Nanit Date: Fri, 27 Nov 2020 00:08:42 +0200 Subject: [PATCH] Added spawn position and dimension in condifgration. Added color codes conversion. PlayerInfo packet --- src/main/java/ru/nanit/limbo/LimboConfig.java | 56 +++++++++++- .../limbo/connection/ClientConnection.java | 19 +++- .../packets/play/PacketPlayerInfo.java | 35 ++++++++ .../nanit/limbo/protocol/registry/State.java | 51 +---------- .../ru/nanit/limbo/server/LimboServer.java | 2 +- src/main/java/ru/nanit/limbo/util/Colors.java | 14 +++ .../nanit/limbo/world/DimensionRegistry.java | 90 ++++++++++++++++--- src/main/resources/settings.properties | 12 ++- 8 files changed, 206 insertions(+), 73 deletions(-) create mode 100644 src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java create mode 100644 src/main/java/ru/nanit/limbo/util/Colors.java diff --git a/src/main/java/ru/nanit/limbo/LimboConfig.java b/src/main/java/ru/nanit/limbo/LimboConfig.java index 89e787d..1dc7189 100644 --- a/src/main/java/ru/nanit/limbo/LimboConfig.java +++ b/src/main/java/ru/nanit/limbo/LimboConfig.java @@ -1,6 +1,8 @@ package ru.nanit.limbo; import ru.nanit.limbo.protocol.packets.play.PacketBossBar; +import ru.nanit.limbo.util.Colors; +import ru.nanit.limbo.util.Logger; import java.io.IOException; import java.nio.file.Files; @@ -12,6 +14,8 @@ public final class LimboConfig { private static String host; private static int port; private static int maxPlayers; + private static String dimensionType; + private static SpawnPosition spawnPosition; private static IpForwardingType ipForwardingType; private static long readTimeout; private static PingData pingData; @@ -30,23 +34,36 @@ public final class LimboConfig { port = Integer.parseInt(props.getProperty("port")); maxPlayers = Integer.parseInt(props.getProperty("max-players")); + + dimensionType = props.getProperty("dimension"); + + String[] posData = props.getProperty("spawn-position").split(","); + + if (posData.length != 3){ + throw new IOException("Invalid spawn position. Check it in the settings.properties file"); + } + + spawnPosition = new SpawnPosition(Double.parseDouble(posData[0]), + Double.parseDouble(posData[1]), + Double.parseDouble(posData[2])); + ipForwardingType = IpForwardingType.valueOf(props.getProperty("ip-forwarding").toUpperCase()); readTimeout = Long.parseLong(props.getProperty("read-timeout")); pingData = new PingData(); pingData.setVersion(props.getProperty("ping-version")); - pingData.setDescription(props.getProperty("ping-description")); + pingData.setDescription(Colors.of(props.getProperty("ping-description"))); debugLevel = Integer.parseInt(props.getProperty("debug-level")); joinMessages = new JoinMessages(); if(props.containsKey("join-message")){ - joinMessages.setChatMessage(props.getProperty("join-message")); + joinMessages.setChatMessage(Colors.of(props.getProperty("join-message"))); } if(props.containsKey("join-bossbar-text")){ - joinMessages.setBossBarText(props.getProperty("join-bossbar-text")); + joinMessages.setBossBarText(Colors.of(props.getProperty("join-bossbar-text"))); joinMessages.setBossBarHealth(Float.parseFloat(props.getProperty("join-bossbar-health"))); joinMessages.setBossBarColor(PacketBossBar.Color.valueOf( props.getProperty("join-bossbar-color").toUpperCase())); @@ -67,6 +84,14 @@ public final class LimboConfig { return maxPlayers; } + public static String getDimensionType() { + return dimensionType; + } + + public static SpawnPosition getSpawnPosition() { + return spawnPosition; + } + public static IpForwardingType getIpForwardingType() { return ipForwardingType; } @@ -93,6 +118,31 @@ public final class LimboConfig { MODERN } + public static class SpawnPosition { + + private final double x; + private final double y; + private final double z; + + public SpawnPosition(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public double getX() { + return x; + } + + public double getY() { + return y; + } + + public double getZ() { + return z; + } + } + public static class PingData { private String version; diff --git a/src/main/java/ru/nanit/limbo/connection/ClientConnection.java b/src/main/java/ru/nanit/limbo/connection/ClientConnection.java index 142b0be..8e0f7c8 100644 --- a/src/main/java/ru/nanit/limbo/connection/ClientConnection.java +++ b/src/main/java/ru/nanit/limbo/connection/ClientConnection.java @@ -38,6 +38,10 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { return uuid; } + public String getUsername() { + return username; + } + public ClientConnection(Channel channel, LimboServer server){ this.server = server; this.channel = channel; @@ -125,19 +129,26 @@ public class ClientConnection extends ChannelInboundHandlerAdapter { joinGame.setWorldNames("minecraft:world"); joinGame.setHashedSeed(0); joinGame.setDimensionCodec(DimensionRegistry.getCodec()); - joinGame.setDimension(DimensionRegistry.getDimension()); + joinGame.setDimension(DimensionRegistry.getDefaultDimension()); PacketPlayerPositionAndLook positionAndLook = new PacketPlayerPositionAndLook(); - positionAndLook.setX(0.0); - positionAndLook.setY(0.0); - positionAndLook.setZ(0.0); + positionAndLook.setX(LimboConfig.getSpawnPosition().getX()); + positionAndLook.setY(LimboConfig.getSpawnPosition().getY()); + positionAndLook.setZ(LimboConfig.getSpawnPosition().getZ()); positionAndLook.setYaw(90.0F); positionAndLook.setPitch(0.0F); positionAndLook.setTeleportId(ThreadLocalRandom.current().nextInt()); + PacketPlayerInfo info = new PacketPlayerInfo(); + + info.setConnection(this); + info.setGameMode(2); + sendPacket(joinGame); sendPacket(positionAndLook); + sendPacket(info); + sendKeepAlive(); if (server.getJoinMessage() != null){ diff --git a/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java b/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java new file mode 100644 index 0000000..e7b0856 --- /dev/null +++ b/src/main/java/ru/nanit/limbo/protocol/packets/play/PacketPlayerInfo.java @@ -0,0 +1,35 @@ +package ru.nanit.limbo.protocol.packets.play; + +import ru.nanit.limbo.connection.ClientConnection; +import ru.nanit.limbo.protocol.ByteMessage; +import ru.nanit.limbo.protocol.PacketOut; + +/** + * This packet wrapper used only for ADD_PLAYER action + */ +public class PacketPlayerInfo implements PacketOut { + + private int gameMode; + private ClientConnection connection; + + public void setConnection(ClientConnection connection) { + this.connection = connection; + } + + public void setGameMode(int gameMode) { + this.gameMode = gameMode; + } + + @Override + public void encode(ByteMessage msg) { + msg.writeVarInt(0); + msg.writeVarInt(1); + msg.writeUuid(connection.getUuid()); + msg.writeString(connection.getUsername()); + msg.writeVarInt(0); + msg.writeVarInt(gameMode); + msg.writeVarInt(60); + msg.writeBoolean(false); + } + +} diff --git a/src/main/java/ru/nanit/limbo/protocol/registry/State.java b/src/main/java/ru/nanit/limbo/protocol/registry/State.java index 9efafcc..55e625a 100644 --- a/src/main/java/ru/nanit/limbo/protocol/registry/State.java +++ b/src/main/java/ru/nanit/limbo/protocol/registry/State.java @@ -42,6 +42,7 @@ public enum State { clientBound.register(0x1F, PacketKeepAlive::new); clientBound.register(0x0E, PacketChatMessage::new); clientBound.register(0x0C, PacketBossBar::new); + clientBound.register(0x32, PacketPlayerInfo::new); } }; @@ -86,54 +87,4 @@ public enum State { } - /* - - Temporary don't needed - - public static class PacketVersionRegistry { - - private final Map> MAPPINGS = new HashMap<>(); - - public PacketIdRegistry getRegistry(Version version){ - PacketIdRegistry registry = MAPPINGS.get(version); - return registry != null ? registry : MAPPINGS.get(version.getClosest(MAPPINGS.keySet())); - } - - public void register(Version version, int packetId, Supplier supplier){ - PacketIdRegistry registry = (PacketIdRegistry) MAPPINGS.computeIfAbsent(version, PacketIdRegistry::new); - registry.register(packetId, supplier); - } - - public static class PacketIdRegistry { - - private final Version version; - private final Map> packetsById = new HashMap<>(); - private final Map, Integer> packetIdByClass = new HashMap<>(); - - public PacketIdRegistry(Version version){ - this.version = version; - } - - public Version getVersion(){ - return version; - } - - public Packet getPacket(int packetId){ - Supplier supplier = packetsById.get(packetId); - return supplier == null ? null : supplier.get(); - } - - public int getPacketId(Class packetClass){ - return packetIdByClass.getOrDefault(packetClass, -1); - } - - public void register(int packetId, Supplier supplier){ - packetsById.put(packetId, supplier); - packetIdByClass.put(supplier.get().getClass(), packetId); - } - - } - - }*/ - } diff --git a/src/main/java/ru/nanit/limbo/server/LimboServer.java b/src/main/java/ru/nanit/limbo/server/LimboServer.java index 31a90cb..865fad5 100644 --- a/src/main/java/ru/nanit/limbo/server/LimboServer.java +++ b/src/main/java/ru/nanit/limbo/server/LimboServer.java @@ -51,7 +51,7 @@ public final class LimboServer { Logger.info("Starting server..."); LimboConfig.load(Paths.get("./settings.properties")); - DimensionRegistry.init(); + DimensionRegistry.init(LimboConfig.getDimensionType()); initializeInGameData(); diff --git a/src/main/java/ru/nanit/limbo/util/Colors.java b/src/main/java/ru/nanit/limbo/util/Colors.java new file mode 100644 index 0000000..fc9e83a --- /dev/null +++ b/src/main/java/ru/nanit/limbo/util/Colors.java @@ -0,0 +1,14 @@ +package ru.nanit.limbo.util; + +public final class Colors { + + private static final char CHAR_FROM = '\u0026'; + private static final char CHAR_TO = '\u00A7'; + + private Colors(){} + + public static String of(String text){ + return text.replace(CHAR_FROM, CHAR_TO); + } + +} diff --git a/src/main/java/ru/nanit/limbo/world/DimensionRegistry.java b/src/main/java/ru/nanit/limbo/world/DimensionRegistry.java index e3b243b..2993013 100644 --- a/src/main/java/ru/nanit/limbo/world/DimensionRegistry.java +++ b/src/main/java/ru/nanit/limbo/world/DimensionRegistry.java @@ -2,14 +2,51 @@ package ru.nanit.limbo.world; import net.kyori.adventure.nbt.CompoundBinaryTag; import net.kyori.adventure.nbt.ListBinaryTag; +import ru.nanit.limbo.util.Logger; public final class DimensionRegistry { - private static CompoundBinaryTag CODEC; - private static CompoundBinaryTag DIMENSION; + private static CompoundBinaryTag codec; + private static CompoundBinaryTag defaultDimension; - public static void init(){ - DIMENSION = CompoundBinaryTag.builder() + public static void init(String defaultDimensionName){ + CompoundBinaryTag overworld = CompoundBinaryTag.builder() + .putString("name", "minecraft:overworld") + .putByte("piglin_safe", (byte) 0) + .putByte("natural", (byte) 0) + .putFloat("ambient_light", 0.0F) + .putString("infiniburn", "minecraft:infiniburn_overworld") + .putByte("respawn_anchor_works", (byte) 0) + .putByte("has_skylight", (byte) 0) + .putByte("bed_works", (byte) 0) + .putString("effects", "minecraft:overworld") + .putLong("fixed_time", 6000L) + .putByte("has_raids", (byte) 1) + .putInt("logical_height", 256) + .putDouble("coordinate_scale", 1.0) + .putByte("ultrawarm", (byte) 0) + .putByte("has_ceiling", (byte) 0) + .build(); + + CompoundBinaryTag nether = CompoundBinaryTag.builder() + .putString("name", "minecraft:the_nether") + .putByte("piglin_safe", (byte) 0) + .putByte("natural", (byte) 0) + .putFloat("ambient_light", 0.0F) + .putString("infiniburn", "minecraft:infiniburn_nether") + .putByte("respawn_anchor_works", (byte) 0) + .putByte("has_skylight", (byte) 0) + .putByte("bed_works", (byte) 0) + .putString("effects", "minecraft:the_nether") + .putLong("fixed_time", 18000L) + .putByte("has_raids", (byte) 1) + .putInt("logical_height", 128) + .putDouble("coordinate_scale", 1.0) + .putByte("ultrawarm", (byte) 0) + .putByte("has_ceiling", (byte) 0) + .build(); + + CompoundBinaryTag theEnd = CompoundBinaryTag.builder() .putString("name", "minecraft:the_end") .putByte("piglin_safe", (byte) 0) .putByte("natural", (byte) 0) @@ -27,10 +64,22 @@ public final class DimensionRegistry { .putByte("has_ceiling", (byte) 0) .build(); - CompoundBinaryTag dimensionData = CompoundBinaryTag.builder() + CompoundBinaryTag overworldData = CompoundBinaryTag.builder() + .putString("name", "minecraft:overworld") + .putInt("id", 2) + .put("element", overworld) + .build(); + + CompoundBinaryTag netherData = CompoundBinaryTag.builder() + .putString("name", "minecraft:the_nether") + .putInt("id", 2) + .put("element", nether) + .build(); + + CompoundBinaryTag endData = CompoundBinaryTag.builder() .putString("name", "minecraft:the_end") .putInt("id", 2) - .put("element", DIMENSION) + .put("element", theEnd) .build(); CompoundBinaryTag plains = CompoundBinaryTag.builder() @@ -58,11 +107,13 @@ public final class DimensionRegistry { .build()) .build(); - CODEC = CompoundBinaryTag.builder() + codec = CompoundBinaryTag.builder() .put("minecraft:dimension_type", CompoundBinaryTag.builder() .putString("type", "minecraft:dimension_type") .put("value", ListBinaryTag.builder() - .add(dimensionData) + .add(overworldData) + .add(netherData) + .add(endData) .build()) .build()) .put("minecraft:worldgen/biome", CompoundBinaryTag.builder() @@ -72,14 +123,29 @@ public final class DimensionRegistry { .build()) .build()) .build(); + + switch (defaultDimensionName.toLowerCase()){ + case "overworld": + defaultDimension = overworld; + break; + case "nether": + defaultDimension = nether; + break; + case "the_end": + defaultDimension = theEnd; + break; + default: + defaultDimension = theEnd; + Logger.error("Undefined dimension type: '%s'. Using THE_END as default", defaultDimensionName); + break; + } } public static CompoundBinaryTag getCodec(){ - return CODEC; + return codec; } - public static CompoundBinaryTag getDimension(){ - return DIMENSION; + public static CompoundBinaryTag getDefaultDimension() { + return defaultDimension; } - } diff --git a/src/main/resources/settings.properties b/src/main/resources/settings.properties index 7574b19..c243847 100644 --- a/src/main/resources/settings.properties +++ b/src/main/resources/settings.properties @@ -11,11 +11,17 @@ port=65535 # Max amount of players can join to server max-players=100 +# Available dimensions: OVERWORLD, NETHER, THE_END +dimension=THE_END + +# Spawn position in the world in format x,y,z +spawn-position=0.0,65.0,0.0 + # Version string when client version is not compatible with server one ping-version=NanoLimbo # Server's description component -ping-description={"text": "NanoLimbo"} +ping-description={"text": "&9NanoLimbo"} # Player info forwarding support. Available types: NONE, LEGACY, MODERN # MODERN - Velocity native forwarding type. @@ -40,7 +46,7 @@ debug-level=3 # ======= In-game Data ======= # # Message when player join to server. Comment this parameter to disable -join-message={"text": "Welcome to the Limbo!"} +join-message={"text": "&eWelcome to the Limbo!"} # Bossbar text. Comment this parameter to disable bossbar join-bossbar-text={"text": "Welcome to the Limbo!"} @@ -56,7 +62,7 @@ join-bossbar-health=1.0 # - YELLOW # - PURPLE # - WHITE -join-bossbar-color=RED +join-bossbar-color=PINK # Available bossbar divisions: # - SOLID