From f236a9b01eea24d60c7218824e009479e42c0545 Mon Sep 17 00:00:00 2001 From: Sculas Date: Wed, 20 Mar 2024 18:12:48 +0100 Subject: [PATCH 1/6] fix: don't spam empty chunk packets --- .../limbo/player/PlayerInteractManager.java | 224 +++++++++--------- 1 file changed, 116 insertions(+), 108 deletions(-) diff --git a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java index 719d242..e76157c 100644 --- a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java +++ b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java @@ -30,6 +30,7 @@ import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityDestroy; import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata; import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnEntity; import com.loohp.limbo.network.protocol.packets.PacketPlayOutUnloadChunk; +import com.loohp.limbo.utils.GameMode; import com.loohp.limbo.world.ChunkPosition; import com.loohp.limbo.world.World; import net.querz.mca.Chunk; @@ -46,118 +47,125 @@ import java.util.Set; import java.util.stream.Collectors; public class PlayerInteractManager { - - private Player player; - - private Set entities; - private Map currentViewing; - - public PlayerInteractManager() { - this.player = null; - this.entities = new HashSet<>(); - this.currentViewing = new HashMap<>(); - } - - protected void setPlayer(Player player) { - if (this.player == null) { - this.player = player; - } else { - throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created"); - } - } - - public Player getPlayer() { - return player; - } - - public void update() throws IOException { - if (player.clientConnection.getClientState() != ClientConnection.ClientState.PLAY) { - return; - } - int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance(); - int viewDistanceBlocks = viewDistanceChunks << 4; - Location location = player.getLocation(); - Set entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet()); - for (Entity entity : entitiesInRange) { - if (!entities.contains(entity)) { - PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), 0, (short) 0, (short) 0, (short) 0); - player.clientConnection.sendPacket(packet); + private Player player; - PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity); - player.clientConnection.sendPacket(meta); - } - } - List ids = new ArrayList<>(); - for (Entity entity : entities) { - if (!entitiesInRange.contains(entity)) { - ids.add(entity.getEntityId()); - } - } - for (int id : ids) { - PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(id); - player.clientConnection.sendPacket(packet); - } - - entities = entitiesInRange; - - int playerChunkX = (int) location.getX() >> 4; - int playerChunkZ = (int) location.getZ() >> 4; - World world = location.getWorld(); - - Map chunksInRange = new HashMap<>(); - - for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) { - for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) { - Chunk chunk = world.getChunkAt(x, z); - if (chunk != null) { - chunksInRange.put(new ChunkPosition(world, x, z), chunk); - } else { - chunksInRange.put(new ChunkPosition(world, x, z), World.EMPTY_CHUNK); - } - } - } - - for (Entry entry : currentViewing.entrySet()) { - ChunkPosition chunkPos = entry.getKey(); - if (!chunksInRange.containsKey(chunkPos)) { - PacketPlayOutUnloadChunk packet = new PacketPlayOutUnloadChunk(chunkPos.getChunkX(), chunkPos.getChunkZ()); - player.clientConnection.sendPacket(packet); - } - } + private Set entities; + private Map currentViewing; - int counter = 0; - ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket(); - player.clientConnection.sendPacket(chunkBatchStartPacket); - for (Entry entry : chunksInRange.entrySet()) { - ChunkPosition chunkPos = entry.getKey(); - if (!currentViewing.containsKey(chunkPos)) { - Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); - if (chunk == null) { - ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList()); - player.clientConnection.sendPacket(chunkdata); - } else { - List blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); - if (blockChunk == null) { - blockChunk = new ArrayList<>(); - } - List skyChunk = null; - if (world.hasSkyLight()) { - skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); - } - if (skyChunk == null) { - skyChunk = new ArrayList<>(); - } - ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk); - player.clientConnection.sendPacket(chunkdata); - } - counter++; + public PlayerInteractManager() { + this.player = null; + this.entities = new HashSet<>(); + this.currentViewing = new HashMap<>(); + } + + protected void setPlayer(Player player) { + if (this.player == null) { + this.player = player; + } else { + throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created"); + } + } + + public Player getPlayer() { + return player; + } + + public void update() throws IOException { + if (player.clientConnection.getClientState() != ClientConnection.ClientState.PLAY && !player.clientConnection.isReady()) { + return; + } + + int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance(); + int viewDistanceBlocks = viewDistanceChunks << 4; + Location location = player.getLocation(); + Set entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet()); + for (Entity entity : entitiesInRange) { + if (!entities.contains(entity)) { + PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), 0, (short) 0, (short) 0, (short) 0); + player.clientConnection.sendPacket(packet); + + PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity); + player.clientConnection.sendPacket(meta); } - } - ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter); - player.clientConnection.sendPacket(chunkBatchFinishedPacket); + } + List ids = new ArrayList<>(); + for (Entity entity : entities) { + if (!entitiesInRange.contains(entity)) { + ids.add(entity.getEntityId()); + } + } + for (int id : ids) { + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(id); + player.clientConnection.sendPacket(packet); + } - currentViewing = chunksInRange; - } + entities = entitiesInRange; + + int playerChunkX = (int) location.getX() >> 4; + int playerChunkZ = (int) location.getZ() >> 4; + World world = location.getWorld(); + + Map chunksInRange = new HashMap<>(); + + for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) { + for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) { + Chunk chunk = world.getChunkAt(x, z); + if (chunk != null) { + chunksInRange.put(new ChunkPosition(world, x, z), chunk); + } else { + chunksInRange.put(new ChunkPosition(world, x, z), World.EMPTY_CHUNK); + } + } + } + + for (ChunkPosition chunkPos : currentViewing.keySet()) { + if (!chunksInRange.containsKey(chunkPos)) { + PacketPlayOutUnloadChunk packet = new PacketPlayOutUnloadChunk(chunkPos.getChunkX(), chunkPos.getChunkZ()); + player.clientConnection.sendPacket(packet); + } + } + + // blocks cannot be broken, so don't send chunks to the client + if (getPlayer().getGamemode() == GameMode.ADVENTURE) { + for (ChunkPosition chunkPos : chunksInRange.keySet()) { + currentViewing.remove(chunkPos); + } + } + + // if we don't have any chunk updates, don't send any packets + if (chunksInRange.isEmpty()) return; + + int counter = 0; + ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket(); + player.clientConnection.sendPacket(chunkBatchStartPacket); + for (Entry entry : chunksInRange.entrySet()) { + ChunkPosition chunkPos = entry.getKey(); + Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); + if (chunk == null) { + ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList()); + player.clientConnection.sendPacket(chunkdata); + } else { + List blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); + if (blockChunk == null) { + blockChunk = new ArrayList<>(); + } + List skyChunk = null; + if (world.hasSkyLight()) { + skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); + } + if (skyChunk == null) { + skyChunk = new ArrayList<>(); + } + ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk); + player.clientConnection.sendPacket(chunkdata); + } + counter++; + } + ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter); + player.clientConnection.sendPacket(chunkBatchFinishedPacket); + + currentViewing = chunksInRange; + } } From 6e12d17cd419e1c1c63a3546edc8b9400b386108 Mon Sep 17 00:00:00 2001 From: Sculas Date: Wed, 20 Mar 2024 18:14:31 +0100 Subject: [PATCH 2/6] fix: fix 1.20.4 getting stuck on loading terrain --- .../loohp/limbo/network/ClientConnection.java | 59 +++---------------- .../packets/PacketPlayOutGameEvent.java | 55 +++++++++++++++++ src/main/resources/mapping.json | 3 +- 3 files changed, 64 insertions(+), 53 deletions(-) create mode 100644 src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java diff --git a/src/main/java/com/loohp/limbo/network/ClientConnection.java b/src/main/java/com/loohp/limbo/network/ClientConnection.java index 0a93dd3..62c89e9 100644 --- a/src/main/java/com/loohp/limbo/network/ClientConnection.java +++ b/src/main/java/com/loohp/limbo/network/ClientConnection.java @@ -41,61 +41,13 @@ import com.loohp.limbo.inventory.AnvilInventory; import com.loohp.limbo.inventory.Inventory; import com.loohp.limbo.inventory.ItemStack; import com.loohp.limbo.location.Location; -import com.loohp.limbo.network.protocol.packets.ClientboundFinishConfigurationPacket; -import com.loohp.limbo.network.protocol.packets.ClientboundRegistryDataPacket; -import com.loohp.limbo.network.protocol.packets.Packet; -import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn; -import com.loohp.limbo.network.protocol.packets.PacketIn; -import com.loohp.limbo.network.protocol.packets.PacketLoginInLoginStart; -import com.loohp.limbo.network.protocol.packets.PacketLoginInPluginMessaging; -import com.loohp.limbo.network.protocol.packets.PacketLoginOutDisconnect; -import com.loohp.limbo.network.protocol.packets.PacketLoginOutLoginSuccess; -import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging; -import com.loohp.limbo.network.protocol.packets.PacketOut; -import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockDig; -import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockPlace; -import com.loohp.limbo.network.protocol.packets.PacketPlayInChat; -import com.loohp.limbo.network.protocol.packets.PacketPlayInCloseWindow; -import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange; -import com.loohp.limbo.network.protocol.packets.PacketPlayInItemName; -import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive; -import com.loohp.limbo.network.protocol.packets.PacketPlayInPickItem; -import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging; -import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition; -import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook; -import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket; +import com.loohp.limbo.network.protocol.packets.*; import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket.Action; -import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation; -import com.loohp.limbo.network.protocol.packets.PacketPlayInSetCreativeSlot; -import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete; -import com.loohp.limbo.network.protocol.packets.PacketPlayInUseItem; -import com.loohp.limbo.network.protocol.packets.PacketPlayInWindowClick; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutDeclareCommands; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutDisconnect; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutKeepAlive; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutLogin; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoAction; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutPluginMessaging; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnPosition; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete; import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete.TabCompleteMatches; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutUpdateViewPosition; -import com.loohp.limbo.network.protocol.packets.PacketStatusInPing; -import com.loohp.limbo.network.protocol.packets.PacketStatusInRequest; -import com.loohp.limbo.network.protocol.packets.PacketStatusOutPong; -import com.loohp.limbo.network.protocol.packets.PacketStatusOutResponse; -import com.loohp.limbo.network.protocol.packets.ServerboundChatCommandPacket; -import com.loohp.limbo.network.protocol.packets.ServerboundFinishConfigurationPacket; -import com.loohp.limbo.network.protocol.packets.ServerboundLoginAcknowledgedPacket; import com.loohp.limbo.player.Player; import com.loohp.limbo.player.PlayerInteractManager; import com.loohp.limbo.player.PlayerInventory; @@ -613,8 +565,6 @@ public class ClientConnection extends Thread { String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "") + ":" + clientSocket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")"; Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!"); - player.playerInteractManager.update(); - PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandsPacket(player); if (declare != null) { sendPacket(declare); @@ -653,8 +603,13 @@ public class ClientConnection extends Thread { // PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123 player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter()); - + + // Start waiting for level chunks + PacketPlayOutGameEvent gameEvent = new PacketPlayOutGameEvent((byte) 13, 0); + sendPacket(gameEvent); + ready = true; + player.playerInteractManager.update(); keepAliveTask = new TimerTask() { @Override diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java new file mode 100644 index 0000000..8eb5f7b --- /dev/null +++ b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java @@ -0,0 +1,55 @@ +/* + * This file is part of Limbo. + * + * Copyright (C) 2022. LoohpJames + * Copyright (C) 2022. Contributors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.loohp.limbo.network.protocol.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +public class PacketPlayOutGameEvent extends PacketOut { + + private byte event; + private float value; + + public PacketPlayOutGameEvent(byte event, float value) { + this.event = event; + this.value = value; + } + + public int getEvent() { + return event; + } + + public float getValue() { + return value; + } + + public byte[] serializePacket() throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + DataOutputStream output = new DataOutputStream(buffer); + output.writeByte(Packet.getPlayOut().get(getClass())); + output.writeByte(Byte.toUnsignedInt(event)); + output.writeFloat(value); + + return buffer.toByteArray(); + } + +} diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index 365880c..a9c649a 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -43,6 +43,7 @@ "PacketPlayOutLogin": "0x29", "PacketPlayOutPositionAndLook": "0x3E", "PacketPlayOutSpawnPosition": "0x54", + "PacketPlayOutGameEvent": "0x20", "ClientboundSystemChatPacket": "0x69", "PacketPlayOutPlayerAbilities": "0x36", "ClientboundLevelChunkWithLightPacket": "0x25", @@ -86,4 +87,4 @@ "PacketStatusOutResponse": "0x00", "PacketStatusOutPong": "0x01" } -} \ No newline at end of file +} From f48c48e6e569df971da9b6e36fc63a68c5f7d819 Mon Sep 17 00:00:00 2001 From: Sculas Date: Wed, 20 Mar 2024 18:19:45 +0100 Subject: [PATCH 3/6] refactor: get mappings from jar rather than file --- src/main/java/com/loohp/limbo/Limbo.java | 182 +++++++++++------------ 1 file changed, 89 insertions(+), 93 deletions(-) diff --git a/src/main/java/com/loohp/limbo/Limbo.java b/src/main/java/com/loohp/limbo/Limbo.java index 11693b2..b4a8acc 100644 --- a/src/main/java/com/loohp/limbo/Limbo.java +++ b/src/main/java/com/loohp/limbo/Limbo.java @@ -102,7 +102,7 @@ public final class Limbo { private static Limbo instance; public static boolean noGui = false; - + public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { for (String flag : args) { if (flag.equals("--nogui") || flag.equals("nogui")) { @@ -129,57 +129,57 @@ public final class Limbo { }); t1.start(); } - + new Limbo(); } - + public static Limbo getInstance() { return instance; } - + //=========================== - + public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4"; public final int SERVER_IMPLEMENTATION_PROTOCOL = 765; public final String LIMBO_IMPLEMENTATION_VERSION; - + private final AtomicBoolean isRunning; - + private final ServerConnection server; private final Console console; - + private final List worlds = new CopyOnWriteArrayList<>(); final Map playersByName = new ConcurrentHashMap<>(); final Map playersByUUID = new ConcurrentHashMap<>(); private final Map bossBars = new ConcurrentHashMap<>(); - + private final ServerProperties properties; - + private final PluginManager pluginManager; private final EventsManager eventsManager; private final PermissionsManager permissionManager; private final File pluginFolder; - + private final File internalDataFolder; - + private final DimensionRegistry dimensionRegistry; - + private final Tick tick; private final LimboScheduler scheduler; - + private final Metrics metrics; - + public final AtomicInteger entityIdCount = new AtomicInteger(); - + @SuppressWarnings("deprecation") private Unsafe unsafe; - + @SuppressWarnings("unchecked") public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { instance = this; unsafe = new Unsafe(this); isRunning = new AtomicBoolean(true); - + if (!noGui) { while (!GUI.loadFinish) { TimeUnit.MILLISECONDS.sleep(500); @@ -188,10 +188,10 @@ public final class Limbo { } else { console = new Console(System.in, System.out, System.err); } - + LIMBO_IMPLEMENTATION_VERSION = getLimboVersion(); console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION); - + String spName = "server.properties"; File sp = new File(spName); if (!sp.exists()) { @@ -202,37 +202,33 @@ public final class Limbo { } } properties = new ServerProperties(sp); - + if (!properties.isBungeecord()) { console.sendMessage("If you are using bungeecord, consider turning that on in the settings!"); } else { console.sendMessage("Starting Limbo server in bungeecord mode!"); } - + internalDataFolder = new File("internal_data"); if (!internalDataFolder.exists()) { internalDataFolder.mkdirs(); } - - String mappingName = "mapping.json"; - File mappingFile = new File(internalDataFolder, mappingName); - if (!mappingFile.exists()) { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(mappingName)) { - Files.copy(in, mappingFile.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } - + console.sendMessage("Loading packet id mappings from mapping.json ..."); - - InputStreamReader reader = new InputStreamReader(Files.newInputStream(mappingFile.toPath()), StandardCharsets.UTF_8); + + InputStream mappingStream = getClass().getClassLoader().getResourceAsStream("mapping.json"); + if (mappingStream == null) { + console.sendMessage("Failed to load mapping.json from jar!"); + System.exit(1); + } + + InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8); JSONObject json = (JSONObject) new JSONParser().parse(reader); reader.close(); - + String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1); int mappingsCount = 0; - + Map> HandshakeIn = new HashMap<>(); for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) { int packetId = Integer.decode((String) key); @@ -240,7 +236,7 @@ public final class Limbo { } Packet.setHandshakeIn(HandshakeIn); mappingsCount += HandshakeIn.size(); - + Map> StatusIn = new HashMap<>(); for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) { int packetId = Integer.decode((String) key); @@ -248,7 +244,7 @@ public final class Limbo { } Packet.setStatusIn(StatusIn); mappingsCount += StatusIn.size(); - + Map, Integer> StatusOut = new HashMap<>(); for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) { Class packetClass = (Class) Class.forName(classPrefix + key); @@ -256,7 +252,7 @@ public final class Limbo { } Packet.setStatusOut(StatusOut); mappingsCount += StatusOut.size(); - + Map> LoginIn = new HashMap<>(); for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) { int packetId = Integer.decode((String) key); @@ -264,7 +260,7 @@ public final class Limbo { } Packet.setLoginIn(LoginIn); mappingsCount += LoginIn.size(); - + Map, Integer> LoginOut = new HashMap<>(); for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) { Class packetClass = (Class) Class.forName(classPrefix + key); @@ -288,7 +284,7 @@ public final class Limbo { } Packet.setConfigurationOut(ConfigurationOut); mappingsCount += ConfigurationOut.size(); - + Map> PlayIn = new HashMap<>(); for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) { int packetId = Integer.decode((String) key); @@ -296,7 +292,7 @@ public final class Limbo { } Packet.setPlayIn(PlayIn); mappingsCount += PlayIn.size(); - + Map, Integer> PlayOut = new HashMap<>(); for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) { Class packetClass = (Class) Class.forName(classPrefix + key); @@ -304,15 +300,15 @@ public final class Limbo { } Packet.setPlayOut(PlayOut); mappingsCount += PlayOut.size(); - + console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!"); - + dimensionRegistry = new DimensionRegistry(); - + worlds.add(loadDefaultWorld()); Location spawn = properties.getWorldSpawn(); properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch())); - + if (!NetworkUtils.available(properties.getServerPort())) { console.sendMessage(""); console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****"); @@ -321,7 +317,7 @@ public final class Limbo { console.sendMessage(""); System.exit(2); } - + String permissionName = "permission.yml"; File permissionFile = new File(permissionName); if (!permissionFile.exists()) { @@ -334,15 +330,15 @@ public final class Limbo { scheduler = new LimboScheduler(); tick = new Tick(this); - + permissionManager = new PermissionsManager(); - permissionManager.loadDefaultPermissionFile(permissionFile); - + permissionManager.loadDefaultPermissionFile(permissionFile); + eventsManager = new EventsManager(); - + pluginFolder = new File("plugins"); pluginFolder.mkdirs(); - + pluginManager = new PluginManager(new DefaultCommands(), pluginFolder); try { Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins"); @@ -352,7 +348,7 @@ public final class Limbo { } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { e.printStackTrace(); } - + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { try { console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); @@ -361,11 +357,11 @@ public final class Limbo { new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); } } - + server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); - + metrics = new Metrics(); - + Runtime.getRuntime().addShutdownHook(new Thread(() -> { Limbo.getInstance().terminate(); })); @@ -377,11 +373,11 @@ public final class Limbo { public Unsafe getUnsafe() { return unsafe; } - + public Tick getHeartBeat() { return tick; } - + public LimboScheduler getScheduler() { return scheduler; } @@ -401,20 +397,20 @@ public final class Limbo { public EventsManager getEventsManager() { return eventsManager; } - + public File getPluginFolder() { return pluginFolder; } - + public PluginManager getPluginManager() { return pluginManager; } private World loadDefaultWorld() throws IOException { console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); - + File schem = new File(properties.getSchemFileName()); - + if (!schem.exists()) { console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!"); console.sendMessage("Creating default world..."); @@ -424,10 +420,10 @@ public final class Limbo { e.printStackTrace(); } } - + try { World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag()); - console.sendMessage("Loaded world " + properties.getLevelName() + "!"); + console.sendMessage("Loaded world " + properties.getLevelName() + "!"); return world; } catch (Throwable e) { console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!"); @@ -437,7 +433,7 @@ public final class Limbo { return null; } } - + public void registerWorld(World world) { if (!worlds.contains(world)) { worlds.add(world); @@ -445,7 +441,7 @@ public final class Limbo { throw new RuntimeException("World already registered"); } } - + public void unregisterWorld(World world) { if (worlds.indexOf(world) == 0) { throw new RuntimeException("World already registered"); @@ -486,7 +482,7 @@ public final class Limbo { public ServerProperties getServerProperties() { return properties; } - + public ServerConnection getServerConnection() { return server; } @@ -494,7 +490,7 @@ public final class Limbo { public Console getConsole() { return console; } - + public Metrics getMetrics() { return metrics; } @@ -502,19 +498,19 @@ public final class Limbo { public Set getPlayers() { return new HashSet<>(playersByUUID.values()); } - + public Player getPlayer(String name) { return playersByName.get(name); } - + public Player getPlayer(UUID uuid) { return playersByUUID.get(uuid); } - + public List getWorlds() { return new ArrayList<>(worlds); } - + public World getWorld(String name) { for (World world : worlds) { if (world.getName().equalsIgnoreCase(name)) { @@ -523,7 +519,7 @@ public final class Limbo { } return null; } - + @SuppressWarnings("unchecked") public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException { JSONObject json = new JSONObject(); @@ -532,14 +528,14 @@ public final class Limbo { versionJson.put("name", version); versionJson.put("protocol", protocol); json.put("version", versionJson); - + JSONObject playersJson = new JSONObject(); playersJson.put("max", maxPlayers); playersJson.put("online", playersOnline); json.put("players", playersJson); - + json.put("description", "%MOTD%"); - + if (favicon != null) { if (favicon.getWidth() == 64 && favicon.getHeight() == 64) { String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png"); @@ -548,30 +544,30 @@ public final class Limbo { console.sendMessage("Server List Favicon must be 64 x 64 in size!"); } } - + JSONObject modInfoJson = new JSONObject(); modInfoJson.put("type", "FML"); modInfoJson.put("modList", new JSONArray()); json.put("modinfo", modInfoJson); - - + + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); treeMap.putAll(json); - + Gson g = new GsonBuilder().create(); return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd)); } - + public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) { String begin = "�1"; return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); } - + protected void terminate() { isRunning.set(false); console.sendMessage("Stopping Server..."); - + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { try { console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); @@ -580,9 +576,9 @@ public final class Limbo { new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); } } - + tick.waitAndKillThreads(5000); - + for (Player player : getPlayers()) { player.disconnect("Server closed"); } @@ -593,23 +589,23 @@ public final class Limbo { e.printStackTrace(); } } - + console.sendMessage("Server closed"); console.logs.close(); } - + public void stopServer() { System.exit(0); } - + public boolean isRunning() { return isRunning.get(); } - + public int getNextEntityId() { return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i); } - + public void dispatchCommand(CommandSender sender, String str) { String[] command; if (str.startsWith("/")) { @@ -619,7 +615,7 @@ public final class Limbo { } dispatchCommand(sender, command); } - + public void dispatchCommand(CommandSender sender, String... args) { try { Limbo.getInstance().getPluginManager().fireExecutors(sender, args); @@ -627,7 +623,7 @@ public final class Limbo { e.printStackTrace(); } } - + private String getLimboVersion() throws IOException { Enumeration manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); while (manifests.hasMoreElements()) { From 342404f58607544b738d453eefb862f0a7f2a1ee Mon Sep 17 00:00:00 2001 From: Sculas Date: Wed, 20 Mar 2024 19:01:59 +0100 Subject: [PATCH 4/6] style: fix formatting --- src/main/java/com/loohp/limbo/Limbo.java | 852 +++++++++--------- .../packets/PacketPlayOutGameEvent.java | 46 +- .../limbo/player/PlayerInteractManager.java | 40 +- 3 files changed, 470 insertions(+), 468 deletions(-) diff --git a/src/main/java/com/loohp/limbo/Limbo.java b/src/main/java/com/loohp/limbo/Limbo.java index b4a8acc..4ff2524 100644 --- a/src/main/java/com/loohp/limbo/Limbo.java +++ b/src/main/java/com/loohp/limbo/Limbo.java @@ -98,129 +98,130 @@ import java.util.stream.Collectors; public final class Limbo { - public static final String LIMBO_BRAND = "Limbo"; + public static final String LIMBO_BRAND = "Limbo"; - private static Limbo instance; - public static boolean noGui = false; + private static Limbo instance; + public static boolean noGui = false; - public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { - for (String flag : args) { - if (flag.equals("--nogui") || flag.equals("nogui")) { - noGui = true; - } else if (flag.equals("--help")) { - System.out.println("Accepted flags:"); - System.out.println(" --nogui <- Disable the GUI"); - System.exit(0); - } else { - System.out.println("Unknown flag: \"" + flag + "\". Ignoring..."); - } - } - if (GraphicsEnvironment.isHeadless()) { - noGui = true; - } - if (!noGui) { - System.out.println("Launching Server GUI.. Add \"--nogui\" in launch arguments to disable"); - Thread t1 = new Thread(() -> { - try { - GUI.main(); - } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { - e.printStackTrace(); - } - }); - t1.start(); - } + public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { + for (String flag : args) { + if (flag.equals("--nogui") || flag.equals("nogui")) { + noGui = true; + } else if (flag.equals("--help")) { + System.out.println("Accepted flags:"); + System.out.println(" --nogui <- Disable the GUI"); + System.exit(0); + } else { + System.out.println("Unknown flag: \"" + flag + "\". Ignoring..."); + } + } + if (GraphicsEnvironment.isHeadless()) { + noGui = true; + } + if (!noGui) { + System.out.println("Launching Server GUI.. Add \"--nogui\" in launch arguments to disable"); + Thread t1 = new Thread(() -> { + try { + GUI.main(); + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | + IllegalAccessException e) { + e.printStackTrace(); + } + }); + t1.start(); + } - new Limbo(); - } + new Limbo(); + } - public static Limbo getInstance() { - return instance; - } + public static Limbo getInstance() { + return instance; + } - //=========================== + //=========================== - public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4"; - public final int SERVER_IMPLEMENTATION_PROTOCOL = 765; - public final String LIMBO_IMPLEMENTATION_VERSION; + public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4"; + public final int SERVER_IMPLEMENTATION_PROTOCOL = 765; + public final String LIMBO_IMPLEMENTATION_VERSION; - private final AtomicBoolean isRunning; + private final AtomicBoolean isRunning; - private final ServerConnection server; - private final Console console; + private final ServerConnection server; + private final Console console; - private final List worlds = new CopyOnWriteArrayList<>(); - final Map playersByName = new ConcurrentHashMap<>(); - final Map playersByUUID = new ConcurrentHashMap<>(); - private final Map bossBars = new ConcurrentHashMap<>(); + private final List worlds = new CopyOnWriteArrayList<>(); + final Map playersByName = new ConcurrentHashMap<>(); + final Map playersByUUID = new ConcurrentHashMap<>(); + private final Map bossBars = new ConcurrentHashMap<>(); - private final ServerProperties properties; + private final ServerProperties properties; - private final PluginManager pluginManager; - private final EventsManager eventsManager; - private final PermissionsManager permissionManager; - private final File pluginFolder; + private final PluginManager pluginManager; + private final EventsManager eventsManager; + private final PermissionsManager permissionManager; + private final File pluginFolder; - private final File internalDataFolder; + private final File internalDataFolder; - private final DimensionRegistry dimensionRegistry; + private final DimensionRegistry dimensionRegistry; - private final Tick tick; - private final LimboScheduler scheduler; + private final Tick tick; + private final LimboScheduler scheduler; - private final Metrics metrics; + private final Metrics metrics; - public final AtomicInteger entityIdCount = new AtomicInteger(); + public final AtomicInteger entityIdCount = new AtomicInteger(); - @SuppressWarnings("deprecation") - private Unsafe unsafe; + @SuppressWarnings("deprecation") + private Unsafe unsafe; - @SuppressWarnings("unchecked") - public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { - instance = this; - unsafe = new Unsafe(this); - isRunning = new AtomicBoolean(true); + @SuppressWarnings("unchecked") + public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { + instance = this; + unsafe = new Unsafe(this); + isRunning = new AtomicBoolean(true); - if (!noGui) { - while (!GUI.loadFinish) { - TimeUnit.MILLISECONDS.sleep(500); - } - console = new Console(null, System.out, System.err); - } else { - console = new Console(System.in, System.out, System.err); - } + if (!noGui) { + while (!GUI.loadFinish) { + TimeUnit.MILLISECONDS.sleep(500); + } + console = new Console(null, System.out, System.err); + } else { + console = new Console(System.in, System.out, System.err); + } - LIMBO_IMPLEMENTATION_VERSION = getLimboVersion(); - console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION); + LIMBO_IMPLEMENTATION_VERSION = getLimboVersion(); + console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION); - String spName = "server.properties"; + String spName = "server.properties"; File sp = new File(spName); if (!sp.exists()) { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(spName)) { + try (InputStream in = getClass().getClassLoader().getResourceAsStream(spName)) { Files.copy(in, sp.toPath()); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); } } properties = new ServerProperties(sp); if (!properties.isBungeecord()) { - console.sendMessage("If you are using bungeecord, consider turning that on in the settings!"); + console.sendMessage("If you are using bungeecord, consider turning that on in the settings!"); } else { - console.sendMessage("Starting Limbo server in bungeecord mode!"); + console.sendMessage("Starting Limbo server in bungeecord mode!"); } internalDataFolder = new File("internal_data"); if (!internalDataFolder.exists()) { - internalDataFolder.mkdirs(); + internalDataFolder.mkdirs(); } console.sendMessage("Loading packet id mappings from mapping.json ..."); - InputStream mappingStream = getClass().getClassLoader().getResourceAsStream("mapping.json"); - if (mappingStream == null) { - console.sendMessage("Failed to load mapping.json from jar!"); - System.exit(1); - } + InputStream mappingStream = getClass().getClassLoader().getResourceAsStream("mapping.json"); + if (mappingStream == null) { + console.sendMessage("Failed to load mapping.json from jar!"); + System.exit(1); + } InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8); JSONObject json = (JSONObject) new JSONParser().parse(reader); @@ -229,107 +230,107 @@ public final class Limbo { String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1); int mappingsCount = 0; - Map> HandshakeIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) { - int packetId = Integer.decode((String) key); - HandshakeIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("HandshakeIn")).get(key))); - } - Packet.setHandshakeIn(HandshakeIn); - mappingsCount += HandshakeIn.size(); + Map> HandshakeIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) { + int packetId = Integer.decode((String) key); + HandshakeIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("HandshakeIn")).get(key))); + } + Packet.setHandshakeIn(HandshakeIn); + mappingsCount += HandshakeIn.size(); - Map> StatusIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) { - int packetId = Integer.decode((String) key); - StatusIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("StatusIn")).get(key))); - } - Packet.setStatusIn(StatusIn); - mappingsCount += StatusIn.size(); + Map> StatusIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) { + int packetId = Integer.decode((String) key); + StatusIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("StatusIn")).get(key))); + } + Packet.setStatusIn(StatusIn); + mappingsCount += StatusIn.size(); - Map, Integer> StatusOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - StatusOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("StatusOut")).get(key))); - } - Packet.setStatusOut(StatusOut); - mappingsCount += StatusOut.size(); + Map, Integer> StatusOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + StatusOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("StatusOut")).get(key))); + } + Packet.setStatusOut(StatusOut); + mappingsCount += StatusOut.size(); - Map> LoginIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) { - int packetId = Integer.decode((String) key); - LoginIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("LoginIn")).get(key))); - } - Packet.setLoginIn(LoginIn); - mappingsCount += LoginIn.size(); + Map> LoginIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) { + int packetId = Integer.decode((String) key); + LoginIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("LoginIn")).get(key))); + } + Packet.setLoginIn(LoginIn); + mappingsCount += LoginIn.size(); - Map, Integer> LoginOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - LoginOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("LoginOut")).get(key))); - } - Packet.setLoginOut(LoginOut); - mappingsCount += LoginOut.size(); + Map, Integer> LoginOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + LoginOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("LoginOut")).get(key))); + } + Packet.setLoginOut(LoginOut); + mappingsCount += LoginOut.size(); - Map> ConfigurationIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("ConfigurationIn")).keySet()) { - int packetId = Integer.decode((String) key); - ConfigurationIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("ConfigurationIn")).get(key))); - } - Packet.setConfigurationIn(ConfigurationIn); - mappingsCount += ConfigurationIn.size(); + Map> ConfigurationIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("ConfigurationIn")).keySet()) { + int packetId = Integer.decode((String) key); + ConfigurationIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("ConfigurationIn")).get(key))); + } + Packet.setConfigurationIn(ConfigurationIn); + mappingsCount += ConfigurationIn.size(); - Map, Integer> ConfigurationOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("ConfigurationOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - ConfigurationOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("ConfigurationOut")).get(key))); - } - Packet.setConfigurationOut(ConfigurationOut); - mappingsCount += ConfigurationOut.size(); + Map, Integer> ConfigurationOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("ConfigurationOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + ConfigurationOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("ConfigurationOut")).get(key))); + } + Packet.setConfigurationOut(ConfigurationOut); + mappingsCount += ConfigurationOut.size(); - Map> PlayIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) { - int packetId = Integer.decode((String) key); - PlayIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("PlayIn")).get(key))); - } - Packet.setPlayIn(PlayIn); - mappingsCount += PlayIn.size(); + Map> PlayIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) { + int packetId = Integer.decode((String) key); + PlayIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("PlayIn")).get(key))); + } + Packet.setPlayIn(PlayIn); + mappingsCount += PlayIn.size(); - Map, Integer> PlayOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - PlayOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("PlayOut")).get(key))); - } - Packet.setPlayOut(PlayOut); - mappingsCount += PlayOut.size(); + Map, Integer> PlayOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + PlayOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("PlayOut")).get(key))); + } + Packet.setPlayOut(PlayOut); + mappingsCount += PlayOut.size(); - console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!"); + console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!"); - dimensionRegistry = new DimensionRegistry(); + dimensionRegistry = new DimensionRegistry(); - worlds.add(loadDefaultWorld()); - Location spawn = properties.getWorldSpawn(); - properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch())); + worlds.add(loadDefaultWorld()); + Location spawn = properties.getWorldSpawn(); + properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch())); - if (!NetworkUtils.available(properties.getServerPort())) { - console.sendMessage(""); - console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****"); - console.sendMessage("*****PORT ALREADY IN USE*****"); - console.sendMessage("*****PERHAPS ANOTHER INSTANCE OF THE SERVER IS ALREADY RUNNING?*****"); - console.sendMessage(""); - System.exit(2); - } + if (!NetworkUtils.available(properties.getServerPort())) { + console.sendMessage(""); + console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****"); + console.sendMessage("*****PORT ALREADY IN USE*****"); + console.sendMessage("*****PERHAPS ANOTHER INSTANCE OF THE SERVER IS ALREADY RUNNING?*****"); + console.sendMessage(""); + System.exit(2); + } - String permissionName = "permission.yml"; + String permissionName = "permission.yml"; File permissionFile = new File(permissionName); if (!permissionFile.exists()) { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) { + try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) { Files.copy(in, permissionFile.toPath()); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); } } scheduler = new LimboScheduler(); - tick = new Tick(this); + tick = new Tick(this); permissionManager = new PermissionsManager(); permissionManager.loadDefaultPermissionFile(permissionFile); @@ -339,323 +340,324 @@ public final class Limbo { pluginFolder = new File("plugins"); pluginFolder.mkdirs(); - pluginManager = new PluginManager(new DefaultCommands(), pluginFolder); - try { - Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins"); - loadPluginsMethod.setAccessible(true); - loadPluginsMethod.invoke(pluginManager); - loadPluginsMethod.setAccessible(false); - } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - e.printStackTrace(); - } + pluginManager = new PluginManager(new DefaultCommands(), pluginFolder); + try { + Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins"); + loadPluginsMethod.setAccessible(true); + loadPluginsMethod.invoke(pluginManager); + loadPluginsMethod.setAccessible(false); + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | + InvocationTargetException e) { + e.printStackTrace(); + } - for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { - try { - console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); - plugin.onEnable(); - } catch (Throwable e) { - new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); - } - } + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { + try { + console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); + plugin.onEnable(); + } catch (Throwable e) { + new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); + } + } - server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); + server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); - metrics = new Metrics(); + metrics = new Metrics(); - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - Limbo.getInstance().terminate(); - })); + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + Limbo.getInstance().terminate(); + })); - console.run(); - } + console.run(); + } - @Deprecated - public Unsafe getUnsafe() { - return unsafe; - } + @Deprecated + public Unsafe getUnsafe() { + return unsafe; + } - public Tick getHeartBeat() { - return tick; - } + public Tick getHeartBeat() { + return tick; + } - public LimboScheduler getScheduler() { - return scheduler; - } + public LimboScheduler getScheduler() { + return scheduler; + } - public DimensionRegistry getDimensionRegistry() { - return dimensionRegistry; - } + public DimensionRegistry getDimensionRegistry() { + return dimensionRegistry; + } - public PermissionsManager getPermissionsManager() { - return permissionManager; - } + public PermissionsManager getPermissionsManager() { + return permissionManager; + } - public File getInternalDataFolder() { - return internalDataFolder; - } + public File getInternalDataFolder() { + return internalDataFolder; + } - public EventsManager getEventsManager() { - return eventsManager; - } + public EventsManager getEventsManager() { + return eventsManager; + } - public File getPluginFolder() { - return pluginFolder; - } + public File getPluginFolder() { + return pluginFolder; + } - public PluginManager getPluginManager() { - return pluginManager; - } + public PluginManager getPluginManager() { + return pluginManager; + } - private World loadDefaultWorld() throws IOException { - console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); + private World loadDefaultWorld() throws IOException { + console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); - File schem = new File(properties.getSchemFileName()); + File schem = new File(properties.getSchemFileName()); - if (!schem.exists()) { - console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!"); - console.sendMessage("Creating default world..."); - try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("spawn.schem")) { - Files.copy(in, schem.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } + if (!schem.exists()) { + console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!"); + console.sendMessage("Creating default world..."); + try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("spawn.schem")) { + Files.copy(in, schem.toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } - try { - World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag()); - console.sendMessage("Loaded world " + properties.getLevelName() + "!"); - return world; - } catch (Throwable e) { - console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!"); - e.printStackTrace(); - console.sendMessage("Server will exit!"); - System.exit(1); - return null; - } - } + try { + World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag()); + console.sendMessage("Loaded world " + properties.getLevelName() + "!"); + return world; + } catch (Throwable e) { + console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!"); + e.printStackTrace(); + console.sendMessage("Server will exit!"); + System.exit(1); + return null; + } + } - public void registerWorld(World world) { - if (!worlds.contains(world)) { - worlds.add(world); - } else { - throw new RuntimeException("World already registered"); - } - } + public void registerWorld(World world) { + if (!worlds.contains(world)) { + worlds.add(world); + } else { + throw new RuntimeException("World already registered"); + } + } - public void unregisterWorld(World world) { - if (worlds.indexOf(world) == 0) { - throw new RuntimeException("World already registered"); - } else if (!worlds.contains(world)) { - throw new RuntimeException("World not registered"); - } else { - for (Player player : world.getPlayers()) { - player.teleport(properties.getWorldSpawn()); - } - worlds.remove(world); - } - } + public void unregisterWorld(World world) { + if (worlds.indexOf(world) == 0) { + throw new RuntimeException("World already registered"); + } else if (!worlds.contains(world)) { + throw new RuntimeException("World not registered"); + } else { + for (Player player : world.getPlayers()) { + player.teleport(properties.getWorldSpawn()); + } + worlds.remove(world); + } + } - public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) { - KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags)))); - bossBars.put(Key, keyedBossBar); - return keyedBossBar; - } + public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) { + KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags)))); + bossBars.put(Key, keyedBossBar); + return keyedBossBar; + } - public void removeBossBar(Key Key) { - KeyedBossBar keyedBossBar = bossBars.remove(Key); - keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a()); - keyedBossBar.getUnsafe().b(); - PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE); - for (Player player : keyedBossBar.getPlayers()) { - try { - player.clientConnection.sendPacket(packetPlayOutBoss); - } catch (IOException e) { - e.printStackTrace(); - } - } - } + public void removeBossBar(Key Key) { + KeyedBossBar keyedBossBar = bossBars.remove(Key); + keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a()); + keyedBossBar.getUnsafe().b(); + PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE); + for (Player player : keyedBossBar.getPlayers()) { + try { + player.clientConnection.sendPacket(packetPlayOutBoss); + } catch (IOException e) { + e.printStackTrace(); + } + } + } - public Map getBossBars() { - return Collections.unmodifiableMap(bossBars); - } + public Map getBossBars() { + return Collections.unmodifiableMap(bossBars); + } - public ServerProperties getServerProperties() { - return properties; - } + public ServerProperties getServerProperties() { + return properties; + } - public ServerConnection getServerConnection() { - return server; - } + public ServerConnection getServerConnection() { + return server; + } - public Console getConsole() { - return console; - } + public Console getConsole() { + return console; + } - public Metrics getMetrics() { - return metrics; - } + public Metrics getMetrics() { + return metrics; + } - public Set getPlayers() { - return new HashSet<>(playersByUUID.values()); - } + public Set getPlayers() { + return new HashSet<>(playersByUUID.values()); + } - public Player getPlayer(String name) { - return playersByName.get(name); - } + public Player getPlayer(String name) { + return playersByName.get(name); + } - public Player getPlayer(UUID uuid) { - return playersByUUID.get(uuid); - } + public Player getPlayer(UUID uuid) { + return playersByUUID.get(uuid); + } - public List getWorlds() { - return new ArrayList<>(worlds); - } + public List getWorlds() { + return new ArrayList<>(worlds); + } - public World getWorld(String name) { - for (World world : worlds) { - if (world.getName().equalsIgnoreCase(name)) { - return world; - } - } - return null; - } + public World getWorld(String name) { + for (World world : worlds) { + if (world.getName().equalsIgnoreCase(name)) { + return world; + } + } + return null; + } - @SuppressWarnings("unchecked") - public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException { - JSONObject json = new JSONObject(); + @SuppressWarnings("unchecked") + public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException { + JSONObject json = new JSONObject(); - JSONObject versionJson = new JSONObject(); - versionJson.put("name", version); - versionJson.put("protocol", protocol); - json.put("version", versionJson); + JSONObject versionJson = new JSONObject(); + versionJson.put("name", version); + versionJson.put("protocol", protocol); + json.put("version", versionJson); - JSONObject playersJson = new JSONObject(); - playersJson.put("max", maxPlayers); - playersJson.put("online", playersOnline); - json.put("players", playersJson); + JSONObject playersJson = new JSONObject(); + playersJson.put("max", maxPlayers); + playersJson.put("online", playersOnline); + json.put("players", playersJson); - json.put("description", "%MOTD%"); + json.put("description", "%MOTD%"); - if (favicon != null) { - if (favicon.getWidth() == 64 && favicon.getHeight() == 64) { - String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png"); - json.put("favicon", base64); - } else { - console.sendMessage("Server List Favicon must be 64 x 64 in size!"); - } - } + if (favicon != null) { + if (favicon.getWidth() == 64 && favicon.getHeight() == 64) { + String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png"); + json.put("favicon", base64); + } else { + console.sendMessage("Server List Favicon must be 64 x 64 in size!"); + } + } - JSONObject modInfoJson = new JSONObject(); - modInfoJson.put("type", "FML"); - modInfoJson.put("modList", new JSONArray()); - json.put("modinfo", modInfoJson); + JSONObject modInfoJson = new JSONObject(); + modInfoJson.put("type", "FML"); + modInfoJson.put("modList", new JSONArray()); + json.put("modinfo", modInfoJson); - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - treeMap.putAll(json); + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.putAll(json); - Gson g = new GsonBuilder().create(); + Gson g = new GsonBuilder().create(); - return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd)); - } + return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd)); + } - public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) { - String begin = "�1"; - return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); - } + public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) { + String begin = "�1"; + return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); + } - protected void terminate() { - isRunning.set(false); - console.sendMessage("Stopping Server..."); + protected void terminate() { + isRunning.set(false); + console.sendMessage("Stopping Server..."); - for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { - try { - console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); - plugin.onDisable(); - } catch (Throwable e) { - new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); - } - } + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { + try { + console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); + plugin.onDisable(); + } catch (Throwable e) { + new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); + } + } - tick.waitAndKillThreads(5000); + tick.waitAndKillThreads(5000); - for (Player player : getPlayers()) { - player.disconnect("Server closed"); - } - while (!getPlayers().isEmpty()) { - try { - TimeUnit.MILLISECONDS.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + for (Player player : getPlayers()) { + player.disconnect("Server closed"); + } + while (!getPlayers().isEmpty()) { + try { + TimeUnit.MILLISECONDS.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - console.sendMessage("Server closed"); - console.logs.close(); - } + console.sendMessage("Server closed"); + console.logs.close(); + } - public void stopServer() { - System.exit(0); - } + public void stopServer() { + System.exit(0); + } - public boolean isRunning() { - return isRunning.get(); - } + public boolean isRunning() { + return isRunning.get(); + } - public int getNextEntityId() { - return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i); - } + public int getNextEntityId() { + return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i); + } - public void dispatchCommand(CommandSender sender, String str) { - String[] command; - if (str.startsWith("/")) { - command = CustomStringUtils.splitStringToArgs(str.substring(1)); - } else { - command = CustomStringUtils.splitStringToArgs(str); - } - dispatchCommand(sender, command); - } + public void dispatchCommand(CommandSender sender, String str) { + String[] command; + if (str.startsWith("/")) { + command = CustomStringUtils.splitStringToArgs(str.substring(1)); + } else { + command = CustomStringUtils.splitStringToArgs(str); + } + dispatchCommand(sender, command); + } - public void dispatchCommand(CommandSender sender, String... args) { - try { - Limbo.getInstance().getPluginManager().fireExecutors(sender, args); - } catch (Exception e) { - e.printStackTrace(); - } - } + public void dispatchCommand(CommandSender sender, String... args) { + try { + Limbo.getInstance().getPluginManager().fireExecutors(sender, args); + } catch (Exception e) { + e.printStackTrace(); + } + } - private String getLimboVersion() throws IOException { - Enumeration manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); - while (manifests.hasMoreElements()) { - URL url = manifests.nextElement(); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - Optional line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst(); - if (line.isPresent()) { - return line.get().substring(14).trim(); - } - } - } - return "Unknown"; - } + private String getLimboVersion() throws IOException { + Enumeration manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); + while (manifests.hasMoreElements()) { + URL url = manifests.nextElement(); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + Optional line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst(); + if (line.isPresent()) { + return line.get().substring(14).trim(); + } + } + } + return "Unknown"; + } - public Inventory createInventory(Component title, int slots, InventoryHolder holder) { - return CustomInventory.create(title, slots, holder); - } + public Inventory createInventory(Component title, int slots, InventoryHolder holder) { + return CustomInventory.create(title, slots, holder); + } - public Inventory createInventory(InventoryType type, InventoryHolder holder) { - return createInventory(null, type, holder); - } + public Inventory createInventory(InventoryType type, InventoryHolder holder) { + return createInventory(null, type, holder); + } - public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) { - if (!type.isCreatable()) { - throw new UnsupportedOperationException("This InventoryType cannot be created."); - } - switch (type) { - case ANVIL: - return new AnvilInventory(title, holder); - default: - throw new UnsupportedOperationException("This InventoryType has not been implemented yet."); - } - } + public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) { + if (!type.isCreatable()) { + throw new UnsupportedOperationException("This InventoryType cannot be created."); + } + switch (type) { + case ANVIL: + return new AnvilInventory(title, holder); + default: + throw new UnsupportedOperationException("This InventoryType has not been implemented yet."); + } + } } diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java index 8eb5f7b..276b414 100644 --- a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java +++ b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java @@ -25,31 +25,31 @@ import java.io.IOException; public class PacketPlayOutGameEvent extends PacketOut { - private byte event; - private float value; + private byte event; + private float value; - public PacketPlayOutGameEvent(byte event, float value) { - this.event = event; - this.value = value; - } + public PacketPlayOutGameEvent(byte event, float value) { + this.event = event; + this.value = value; + } - public int getEvent() { - return event; - } - - public float getValue() { - return value; - } - - public byte[] serializePacket() throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - DataOutputStream output = new DataOutputStream(buffer); - output.writeByte(Packet.getPlayOut().get(getClass())); - output.writeByte(Byte.toUnsignedInt(event)); - output.writeFloat(value); + public int getEvent() { + return event; + } - return buffer.toByteArray(); - } + public float getValue() { + return value; + } + + public byte[] serializePacket() throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + + DataOutputStream output = new DataOutputStream(buffer); + output.writeByte(Packet.getPlayOut().get(getClass())); + output.writeByte(Byte.toUnsignedInt(event)); + output.writeFloat(value); + + return buffer.toByteArray(); + } } diff --git a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java index e76157c..82210e2 100644 --- a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java +++ b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java @@ -141,26 +141,26 @@ public class PlayerInteractManager { player.clientConnection.sendPacket(chunkBatchStartPacket); for (Entry entry : chunksInRange.entrySet()) { ChunkPosition chunkPos = entry.getKey(); - Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); - if (chunk == null) { - ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList()); - player.clientConnection.sendPacket(chunkdata); - } else { - List blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); - if (blockChunk == null) { - blockChunk = new ArrayList<>(); - } - List skyChunk = null; - if (world.hasSkyLight()) { - skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); - } - if (skyChunk == null) { - skyChunk = new ArrayList<>(); - } - ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk); - player.clientConnection.sendPacket(chunkdata); - } - counter++; + Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); + if (chunk == null) { + ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList()); + player.clientConnection.sendPacket(chunkdata); + } else { + List blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); + if (blockChunk == null) { + blockChunk = new ArrayList<>(); + } + List skyChunk = null; + if (world.hasSkyLight()) { + skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); + } + if (skyChunk == null) { + skyChunk = new ArrayList<>(); + } + ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk); + player.clientConnection.sendPacket(chunkdata); + } + counter++; } ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter); player.clientConnection.sendPacket(chunkBatchFinishedPacket); From 01d2a3e52866ed55b93fcb06edb7887f87d94c6d Mon Sep 17 00:00:00 2001 From: Sculas Date: Mon, 25 Mar 2024 18:22:44 +0100 Subject: [PATCH 5/6] fix: Fix chunk updates not being sent properly --- .../limbo/player/PlayerInteractManager.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java index 82210e2..9497770 100644 --- a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java +++ b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java @@ -52,11 +52,13 @@ public class PlayerInteractManager { private Set entities; private Map currentViewing; + private final Map chunkUpdates; public PlayerInteractManager() { this.player = null; this.entities = new HashSet<>(); this.currentViewing = new HashMap<>(); + this.chunkUpdates = new HashMap<>(); } protected void setPlayer(Player player) { @@ -126,20 +128,24 @@ public class PlayerInteractManager { } } - // blocks cannot be broken, so don't send chunks to the client + // add chunk candidates for updating + chunkUpdates.clear(); + chunkUpdates.putAll(chunksInRange); + + // blocks cannot be broken, so once we've sent all of them, don't update them anymore if (getPlayer().getGamemode() == GameMode.ADVENTURE) { - for (ChunkPosition chunkPos : chunksInRange.keySet()) { - currentViewing.remove(chunkPos); + for (ChunkPosition chunkPos : currentViewing.keySet()) { + chunkUpdates.remove(chunkPos); } } // if we don't have any chunk updates, don't send any packets - if (chunksInRange.isEmpty()) return; + if (chunkUpdates.isEmpty()) return; int counter = 0; ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket(); player.clientConnection.sendPacket(chunkBatchStartPacket); - for (Entry entry : chunksInRange.entrySet()) { + for (Entry entry : chunkUpdates.entrySet()) { ChunkPosition chunkPos = entry.getKey(); Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); if (chunk == null) { From 8ec7d322d81a0367e40c7f355bab9d75cd430d78 Mon Sep 17 00:00:00 2001 From: LOOHP Date: Mon, 25 Mar 2024 22:03:24 +0000 Subject: [PATCH 6/6] Clean up & Format --- pom.xml | 12 +- src/main/java/com/loohp/limbo/Limbo.java | 1015 ++++++++--------- .../loohp/limbo/network/ClientConnection.java | 63 +- .../packets/PacketPlayOutGameState.java | 56 - ...java => PacketPlayOutGameStateChange.java} | 41 +- .../java/com/loohp/limbo/player/Player.java | 4 +- .../limbo/player/PlayerInteractManager.java | 214 ++-- .../com/loohp/limbo/registry/Registry.java | 15 +- .../loohp/limbo/world/DimensionRegistry.java | 24 +- .../world/GeneratedBlockDataMappings.java | 19 +- src/main/resources/mapping.json | 5 +- 11 files changed, 720 insertions(+), 748 deletions(-) delete mode 100644 src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameState.java rename src/main/java/com/loohp/limbo/network/protocol/packets/{PacketPlayOutGameEvent.java => PacketPlayOutGameStateChange.java} (55%) diff --git a/pom.xml b/pom.xml index 0b08ec8..9deddf1 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ com.loohp Limbo Limbo - 0.7.7-ALPHA + 0.7.8-ALPHA Standalone Limbo Minecraft Server. https://github.com/LOOHP/Limbo @@ -260,31 +260,31 @@ net.kyori adventure-text-serializer-gson - 4.15.0-SNAPSHOT + 4.17.0-SNAPSHOT compile net.kyori adventure-text-serializer-legacy - 4.15.0-SNAPSHOT + 4.17.0-SNAPSHOT compile net.kyori adventure-text-serializer-plain - 4.15.0-SNAPSHOT + 4.17.0-SNAPSHOT compile net.kyori adventure-api - 4.15.0-SNAPSHOT + 4.17.0-SNAPSHOT compile net.kyori adventure-nbt - 4.15.0-SNAPSHOT + 4.17.0-SNAPSHOT compile diff --git a/src/main/java/com/loohp/limbo/Limbo.java b/src/main/java/com/loohp/limbo/Limbo.java index 4ff2524..2c48383 100644 --- a/src/main/java/com/loohp/limbo/Limbo.java +++ b/src/main/java/com/loohp/limbo/Limbo.java @@ -98,566 +98,553 @@ import java.util.stream.Collectors; public final class Limbo { - public static final String LIMBO_BRAND = "Limbo"; + public static final String LIMBO_BRAND = "Limbo"; - private static Limbo instance; - public static boolean noGui = false; - - public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { - for (String flag : args) { - if (flag.equals("--nogui") || flag.equals("nogui")) { - noGui = true; - } else if (flag.equals("--help")) { - System.out.println("Accepted flags:"); - System.out.println(" --nogui <- Disable the GUI"); - System.exit(0); - } else { - System.out.println("Unknown flag: \"" + flag + "\". Ignoring..."); - } - } - if (GraphicsEnvironment.isHeadless()) { - noGui = true; - } - if (!noGui) { - System.out.println("Launching Server GUI.. Add \"--nogui\" in launch arguments to disable"); - Thread t1 = new Thread(() -> { - try { - GUI.main(); - } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | - IllegalAccessException e) { - e.printStackTrace(); - } - }); - t1.start(); - } - - new Limbo(); - } - - public static Limbo getInstance() { - return instance; - } - - //=========================== - - public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4"; - public final int SERVER_IMPLEMENTATION_PROTOCOL = 765; - public final String LIMBO_IMPLEMENTATION_VERSION; - - private final AtomicBoolean isRunning; - - private final ServerConnection server; - private final Console console; - - private final List worlds = new CopyOnWriteArrayList<>(); - final Map playersByName = new ConcurrentHashMap<>(); - final Map playersByUUID = new ConcurrentHashMap<>(); - private final Map bossBars = new ConcurrentHashMap<>(); - - private final ServerProperties properties; - - private final PluginManager pluginManager; - private final EventsManager eventsManager; - private final PermissionsManager permissionManager; - private final File pluginFolder; - - private final File internalDataFolder; - - private final DimensionRegistry dimensionRegistry; - - private final Tick tick; - private final LimboScheduler scheduler; - - private final Metrics metrics; - - public final AtomicInteger entityIdCount = new AtomicInteger(); - - @SuppressWarnings("deprecation") - private Unsafe unsafe; - - @SuppressWarnings("unchecked") - public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { - instance = this; - unsafe = new Unsafe(this); - isRunning = new AtomicBoolean(true); - - if (!noGui) { - while (!GUI.loadFinish) { - TimeUnit.MILLISECONDS.sleep(500); - } - console = new Console(null, System.out, System.err); - } else { - console = new Console(System.in, System.out, System.err); - } - - LIMBO_IMPLEMENTATION_VERSION = getLimboVersion(); - console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION); - - String spName = "server.properties"; + private static Limbo instance; + public static boolean noGui = false; + + public static void main(String args[]) throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { + for (String flag : args) { + if (flag.equals("--nogui") || flag.equals("nogui")) { + noGui = true; + } else if (flag.equals("--help")) { + System.out.println("Accepted flags:"); + System.out.println(" --nogui <- Disable the GUI"); + System.exit(0); + } else { + System.out.println("Unknown flag: \"" + flag + "\". Ignoring..."); + } + } + if (GraphicsEnvironment.isHeadless()) { + noGui = true; + } + if (!noGui) { + System.out.println("Launching Server GUI.. Add \"--nogui\" in launch arguments to disable"); + Thread t1 = new Thread(() -> { + try { + GUI.main(); + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + }); + t1.start(); + } + + new Limbo(); + } + + public static Limbo getInstance() { + return instance; + } + + //=========================== + + public final String SERVER_IMPLEMENTATION_VERSION = "1.20.4"; + public final int SERVER_IMPLEMENTATION_PROTOCOL = 765; + public final String LIMBO_IMPLEMENTATION_VERSION; + + private final AtomicBoolean isRunning; + + private final ServerConnection server; + private final Console console; + + private final List worlds = new CopyOnWriteArrayList<>(); + final Map playersByName = new ConcurrentHashMap<>(); + final Map playersByUUID = new ConcurrentHashMap<>(); + private final Map bossBars = new ConcurrentHashMap<>(); + + private final ServerProperties properties; + + private final PluginManager pluginManager; + private final EventsManager eventsManager; + private final PermissionsManager permissionManager; + private final File pluginFolder; + + private final DimensionRegistry dimensionRegistry; + + private final Tick tick; + private final LimboScheduler scheduler; + + private final Metrics metrics; + + public final AtomicInteger entityIdCount = new AtomicInteger(); + + @SuppressWarnings("deprecation") + private Unsafe unsafe; + + @SuppressWarnings("unchecked") + public Limbo() throws IOException, ParseException, NumberFormatException, ClassNotFoundException, InterruptedException { + instance = this; + unsafe = new Unsafe(this); + isRunning = new AtomicBoolean(true); + + if (!noGui) { + while (!GUI.loadFinish) { + TimeUnit.MILLISECONDS.sleep(500); + } + console = new Console(null, System.out, System.err); + } else { + console = new Console(System.in, System.out, System.err); + } + + LIMBO_IMPLEMENTATION_VERSION = getLimboVersion(); + console.sendMessage("Loading Limbo Version " + LIMBO_IMPLEMENTATION_VERSION + " on Minecraft " + SERVER_IMPLEMENTATION_VERSION); + + String spName = "server.properties"; File sp = new File(spName); if (!sp.exists()) { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(spName)) { + try (InputStream in = getClass().getClassLoader().getResourceAsStream(spName)) { Files.copy(in, sp.toPath()); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); } } properties = new ServerProperties(sp); - + if (!properties.isBungeecord()) { - console.sendMessage("If you are using bungeecord, consider turning that on in the settings!"); + console.sendMessage("If you are using bungeecord, consider turning that on in the settings!"); } else { - console.sendMessage("Starting Limbo server in bungeecord mode!"); + console.sendMessage("Starting Limbo server in bungeecord mode!"); } + + String mappingName = "mapping.json"; + InputStream mappingStream = getClass().getClassLoader().getResourceAsStream(mappingName); + if (mappingStream == null) { + throw new RuntimeException("Failed to load " + mappingName + " from jar!"); + } + + console.sendMessage("Loading packet id mappings..."); - internalDataFolder = new File("internal_data"); - if (!internalDataFolder.exists()) { - internalDataFolder.mkdirs(); - } - - console.sendMessage("Loading packet id mappings from mapping.json ..."); - - InputStream mappingStream = getClass().getClassLoader().getResourceAsStream("mapping.json"); - if (mappingStream == null) { - console.sendMessage("Failed to load mapping.json from jar!"); - System.exit(1); - } - - InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8); + InputStreamReader reader = new InputStreamReader(mappingStream, StandardCharsets.UTF_8); JSONObject json = (JSONObject) new JSONParser().parse(reader); reader.close(); - + String classPrefix = Packet.class.getName().substring(0, Packet.class.getName().lastIndexOf(".") + 1); int mappingsCount = 0; + + Map> HandshakeIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) { + int packetId = Integer.decode((String) key); + HandshakeIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("HandshakeIn")).get(key))); + } + Packet.setHandshakeIn(HandshakeIn); + mappingsCount += HandshakeIn.size(); + + Map> StatusIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) { + int packetId = Integer.decode((String) key); + StatusIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("StatusIn")).get(key))); + } + Packet.setStatusIn(StatusIn); + mappingsCount += StatusIn.size(); + + Map, Integer> StatusOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + StatusOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("StatusOut")).get(key))); + } + Packet.setStatusOut(StatusOut); + mappingsCount += StatusOut.size(); + + Map> LoginIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) { + int packetId = Integer.decode((String) key); + LoginIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("LoginIn")).get(key))); + } + Packet.setLoginIn(LoginIn); + mappingsCount += LoginIn.size(); + + Map, Integer> LoginOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + LoginOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("LoginOut")).get(key))); + } + Packet.setLoginOut(LoginOut); + mappingsCount += LoginOut.size(); - Map> HandshakeIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("HandshakeIn")).keySet()) { - int packetId = Integer.decode((String) key); - HandshakeIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("HandshakeIn")).get(key))); - } - Packet.setHandshakeIn(HandshakeIn); - mappingsCount += HandshakeIn.size(); + Map> ConfigurationIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("ConfigurationIn")).keySet()) { + int packetId = Integer.decode((String) key); + ConfigurationIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("ConfigurationIn")).get(key))); + } + Packet.setConfigurationIn(ConfigurationIn); + mappingsCount += ConfigurationIn.size(); - Map> StatusIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("StatusIn")).keySet()) { - int packetId = Integer.decode((String) key); - StatusIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("StatusIn")).get(key))); - } - Packet.setStatusIn(StatusIn); - mappingsCount += StatusIn.size(); - - Map, Integer> StatusOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("StatusOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - StatusOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("StatusOut")).get(key))); - } - Packet.setStatusOut(StatusOut); - mappingsCount += StatusOut.size(); - - Map> LoginIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("LoginIn")).keySet()) { - int packetId = Integer.decode((String) key); - LoginIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("LoginIn")).get(key))); - } - Packet.setLoginIn(LoginIn); - mappingsCount += LoginIn.size(); - - Map, Integer> LoginOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("LoginOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - LoginOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("LoginOut")).get(key))); - } - Packet.setLoginOut(LoginOut); - mappingsCount += LoginOut.size(); - - Map> ConfigurationIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("ConfigurationIn")).keySet()) { - int packetId = Integer.decode((String) key); - ConfigurationIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("ConfigurationIn")).get(key))); - } - Packet.setConfigurationIn(ConfigurationIn); - mappingsCount += ConfigurationIn.size(); - - Map, Integer> ConfigurationOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("ConfigurationOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - ConfigurationOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("ConfigurationOut")).get(key))); - } - Packet.setConfigurationOut(ConfigurationOut); - mappingsCount += ConfigurationOut.size(); - - Map> PlayIn = new HashMap<>(); - for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) { - int packetId = Integer.decode((String) key); - PlayIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("PlayIn")).get(key))); - } - Packet.setPlayIn(PlayIn); - mappingsCount += PlayIn.size(); - - Map, Integer> PlayOut = new HashMap<>(); - for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) { - Class packetClass = (Class) Class.forName(classPrefix + key); - PlayOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("PlayOut")).get(key))); - } - Packet.setPlayOut(PlayOut); - mappingsCount += PlayOut.size(); - - console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!"); - - dimensionRegistry = new DimensionRegistry(); - - worlds.add(loadDefaultWorld()); - Location spawn = properties.getWorldSpawn(); - properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch())); - - if (!NetworkUtils.available(properties.getServerPort())) { - console.sendMessage(""); - console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****"); - console.sendMessage("*****PORT ALREADY IN USE*****"); - console.sendMessage("*****PERHAPS ANOTHER INSTANCE OF THE SERVER IS ALREADY RUNNING?*****"); - console.sendMessage(""); - System.exit(2); - } - - String permissionName = "permission.yml"; + Map, Integer> ConfigurationOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("ConfigurationOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + ConfigurationOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("ConfigurationOut")).get(key))); + } + Packet.setConfigurationOut(ConfigurationOut); + mappingsCount += ConfigurationOut.size(); + + Map> PlayIn = new HashMap<>(); + for (Object key : ((JSONObject) json.get("PlayIn")).keySet()) { + int packetId = Integer.decode((String) key); + PlayIn.put(packetId, (Class) Class.forName(classPrefix + ((JSONObject) json.get("PlayIn")).get(key))); + } + Packet.setPlayIn(PlayIn); + mappingsCount += PlayIn.size(); + + Map, Integer> PlayOut = new HashMap<>(); + for (Object key : ((JSONObject) json.get("PlayOut")).keySet()) { + Class packetClass = (Class) Class.forName(classPrefix + key); + PlayOut.put(packetClass, Integer.decode((String) ((JSONObject) json.get("PlayOut")).get(key))); + } + Packet.setPlayOut(PlayOut); + mappingsCount += PlayOut.size(); + + console.sendMessage("Loaded all " + mappingsCount + " packet id mappings!"); + + dimensionRegistry = new DimensionRegistry(); + + worlds.add(loadDefaultWorld()); + Location spawn = properties.getWorldSpawn(); + properties.setWorldSpawn(new Location(getWorld(properties.getLevelName().value()), spawn.getX(), spawn.getY(), spawn.getZ(), spawn.getYaw(), spawn.getPitch())); + + if (!NetworkUtils.available(properties.getServerPort())) { + console.sendMessage(""); + console.sendMessage("*****FAILED TO BIND PORT [" + properties.getServerPort() + "]*****"); + console.sendMessage("*****PORT ALREADY IN USE*****"); + console.sendMessage("*****PERHAPS ANOTHER INSTANCE OF THE SERVER IS ALREADY RUNNING?*****"); + console.sendMessage(""); + System.exit(2); + } + + String permissionName = "permission.yml"; File permissionFile = new File(permissionName); if (!permissionFile.exists()) { - try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) { + try (InputStream in = getClass().getClassLoader().getResourceAsStream(permissionName)) { Files.copy(in, permissionFile.toPath()); } catch (IOException e) { - e.printStackTrace(); + e.printStackTrace(); } } scheduler = new LimboScheduler(); - tick = new Tick(this); - + tick = new Tick(this); + permissionManager = new PermissionsManager(); - permissionManager.loadDefaultPermissionFile(permissionFile); - + permissionManager.loadDefaultPermissionFile(permissionFile); + eventsManager = new EventsManager(); - + pluginFolder = new File("plugins"); pluginFolder.mkdirs(); + + pluginManager = new PluginManager(new DefaultCommands(), pluginFolder); + try { + Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins"); + loadPluginsMethod.setAccessible(true); + loadPluginsMethod.invoke(pluginManager); + loadPluginsMethod.setAccessible(false); + } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { + try { + console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); + plugin.onEnable(); + } catch (Throwable e) { + new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); + } + } + + server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); + + metrics = new Metrics(); + + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + Limbo.getInstance().terminate(); + })); - pluginManager = new PluginManager(new DefaultCommands(), pluginFolder); - try { - Method loadPluginsMethod = PluginManager.class.getDeclaredMethod("loadPlugins"); - loadPluginsMethod.setAccessible(true); - loadPluginsMethod.invoke(pluginManager); - loadPluginsMethod.setAccessible(false); - } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | - InvocationTargetException e) { - e.printStackTrace(); - } + console.run(); + } - for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { - try { - console.sendMessage("Enabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); - plugin.onEnable(); - } catch (Throwable e) { - new RuntimeException("Error while enabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); - } - } + @Deprecated + public Unsafe getUnsafe() { + return unsafe; + } + + public Tick getHeartBeat() { + return tick; + } + + public LimboScheduler getScheduler() { + return scheduler; + } - server = new ServerConnection(properties.getServerIp(), properties.getServerPort()); + public DimensionRegistry getDimensionRegistry() { + return dimensionRegistry; + } - metrics = new Metrics(); + public PermissionsManager getPermissionsManager() { + return permissionManager; + } - Runtime.getRuntime().addShutdownHook(new Thread(() -> { - Limbo.getInstance().terminate(); - })); + public EventsManager getEventsManager() { + return eventsManager; + } + + public File getPluginFolder() { + return pluginFolder; + } + + public PluginManager getPluginManager() { + return pluginManager; + } - console.run(); - } + private World loadDefaultWorld() throws IOException { + console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); + + File schem = new File(properties.getSchemFileName()); + + if (!schem.exists()) { + console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!"); + console.sendMessage("Creating default world..."); + try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("spawn.schem")) { + Files.copy(in, schem.toPath()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + try { + World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag()); + console.sendMessage("Loaded world " + properties.getLevelName() + "!"); + return world; + } catch (Throwable e) { + console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!"); + e.printStackTrace(); + console.sendMessage("Server will exit!"); + System.exit(1); + return null; + } + } + + public void registerWorld(World world) { + if (!worlds.contains(world)) { + worlds.add(world); + } else { + throw new RuntimeException("World already registered"); + } + } + + public void unregisterWorld(World world) { + if (worlds.indexOf(world) == 0) { + throw new RuntimeException("World already registered"); + } else if (!worlds.contains(world)) { + throw new RuntimeException("World not registered"); + } else { + for (Player player : world.getPlayers()) { + player.teleport(properties.getWorldSpawn()); + } + worlds.remove(world); + } + } - @Deprecated - public Unsafe getUnsafe() { - return unsafe; - } + public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) { + KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags)))); + bossBars.put(Key, keyedBossBar); + return keyedBossBar; + } - public Tick getHeartBeat() { - return tick; - } + public void removeBossBar(Key Key) { + KeyedBossBar keyedBossBar = bossBars.remove(Key); + keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a()); + keyedBossBar.getUnsafe().b(); + PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE); + for (Player player : keyedBossBar.getPlayers()) { + try { + player.clientConnection.sendPacket(packetPlayOutBoss); + } catch (IOException e) { + e.printStackTrace(); + } + } + } - public LimboScheduler getScheduler() { - return scheduler; - } + public Map getBossBars() { + return Collections.unmodifiableMap(bossBars); + } - public DimensionRegistry getDimensionRegistry() { - return dimensionRegistry; - } + public ServerProperties getServerProperties() { + return properties; + } + + public ServerConnection getServerConnection() { + return server; + } - public PermissionsManager getPermissionsManager() { - return permissionManager; - } + public Console getConsole() { + return console; + } + + public Metrics getMetrics() { + return metrics; + } - public File getInternalDataFolder() { - return internalDataFolder; - } + public Set getPlayers() { + return new HashSet<>(playersByUUID.values()); + } + + public Player getPlayer(String name) { + return playersByName.get(name); + } + + public Player getPlayer(UUID uuid) { + return playersByUUID.get(uuid); + } + + public List getWorlds() { + return new ArrayList<>(worlds); + } + + public World getWorld(String name) { + for (World world : worlds) { + if (world.getName().equalsIgnoreCase(name)) { + return world; + } + } + return null; + } + + @SuppressWarnings("unchecked") + public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException { + JSONObject json = new JSONObject(); - public EventsManager getEventsManager() { - return eventsManager; - } + JSONObject versionJson = new JSONObject(); + versionJson.put("name", version); + versionJson.put("protocol", protocol); + json.put("version", versionJson); + + JSONObject playersJson = new JSONObject(); + playersJson.put("max", maxPlayers); + playersJson.put("online", playersOnline); + json.put("players", playersJson); + + json.put("description", "%MOTD%"); + + if (favicon != null) { + if (favicon.getWidth() == 64 && favicon.getHeight() == 64) { + String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png"); + json.put("favicon", base64); + } else { + console.sendMessage("Server List Favicon must be 64 x 64 in size!"); + } + } + + JSONObject modInfoJson = new JSONObject(); + modInfoJson.put("type", "FML"); + modInfoJson.put("modList", new JSONArray()); + json.put("modinfo", modInfoJson); + + + TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + treeMap.putAll(json); + + Gson g = new GsonBuilder().create(); - public File getPluginFolder() { - return pluginFolder; - } + return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd)); + } + + public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) { + String begin = "�1"; + return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); + } + + protected void terminate() { + isRunning.set(false); + console.sendMessage("Stopping Server..."); + + for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { + try { + console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); + plugin.onDisable(); + } catch (Throwable e) { + new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); + } + } + + tick.waitAndKillThreads(5000); + + for (Player player : getPlayers()) { + player.disconnect("Server closed"); + } + while (!getPlayers().isEmpty()) { + try { + TimeUnit.MILLISECONDS.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + console.sendMessage("Server closed"); + console.logs.close(); + } + + public void stopServer() { + System.exit(0); + } + + public boolean isRunning() { + return isRunning.get(); + } + + public int getNextEntityId() { + return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i); + } + + public void dispatchCommand(CommandSender sender, String str) { + String[] command; + if (str.startsWith("/")) { + command = CustomStringUtils.splitStringToArgs(str.substring(1)); + } else { + command = CustomStringUtils.splitStringToArgs(str); + } + dispatchCommand(sender, command); + } + + public void dispatchCommand(CommandSender sender, String... args) { + try { + Limbo.getInstance().getPluginManager().fireExecutors(sender, args); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private String getLimboVersion() throws IOException { + Enumeration manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); + while (manifests.hasMoreElements()) { + URL url = manifests.nextElement(); + try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { + Optional line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst(); + if (line.isPresent()) { + return line.get().substring(14).trim(); + } + } + } + return "Unknown"; + } - public PluginManager getPluginManager() { - return pluginManager; - } + public Inventory createInventory(Component title, int slots, InventoryHolder holder) { + return CustomInventory.create(title, slots, holder); + } - private World loadDefaultWorld() throws IOException { - console.sendMessage("Loading world " + properties.getLevelName() + " with the schematic file " + properties.getSchemFileName() + " ..."); + public Inventory createInventory(InventoryType type, InventoryHolder holder) { + return createInventory(null, type, holder); + } - File schem = new File(properties.getSchemFileName()); - - if (!schem.exists()) { - console.sendMessage("Schemetic file " + properties.getSchemFileName() + " for world " + properties.getLevelName() + " not found!"); - console.sendMessage("Creating default world..."); - try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream("spawn.schem")) { - Files.copy(in, schem.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - try { - World world = Schematic.toWorld(properties.getLevelName().value(), Environment.fromKey(properties.getLevelDimension()), (CompoundTag) NBTUtil.read(schem).getTag()); - console.sendMessage("Loaded world " + properties.getLevelName() + "!"); - return world; - } catch (Throwable e) { - console.sendMessage("Unable to load world " + properties.getSchemFileName() + "!"); - e.printStackTrace(); - console.sendMessage("Server will exit!"); - System.exit(1); - return null; - } - } - - public void registerWorld(World world) { - if (!worlds.contains(world)) { - worlds.add(world); - } else { - throw new RuntimeException("World already registered"); - } - } - - public void unregisterWorld(World world) { - if (worlds.indexOf(world) == 0) { - throw new RuntimeException("World already registered"); - } else if (!worlds.contains(world)) { - throw new RuntimeException("World not registered"); - } else { - for (Player player : world.getPlayers()) { - player.teleport(properties.getWorldSpawn()); - } - worlds.remove(world); - } - } - - public KeyedBossBar createBossBar(Key Key, Component name, float progress, BossBar.Color color, BossBar.Overlay overlay, BossBar.Flag... flags) { - KeyedBossBar keyedBossBar = com.loohp.limbo.bossbar.Unsafe.a(Key, BossBar.bossBar(name, progress, color, overlay, new HashSet<>(Arrays.asList(flags)))); - bossBars.put(Key, keyedBossBar); - return keyedBossBar; - } - - public void removeBossBar(Key Key) { - KeyedBossBar keyedBossBar = bossBars.remove(Key); - keyedBossBar.getProperties().removeListener(keyedBossBar.getUnsafe().a()); - keyedBossBar.getUnsafe().b(); - PacketPlayOutBoss packetPlayOutBoss = new PacketPlayOutBoss(keyedBossBar, PacketPlayOutBoss.BossBarAction.REMOVE); - for (Player player : keyedBossBar.getPlayers()) { - try { - player.clientConnection.sendPacket(packetPlayOutBoss); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public Map getBossBars() { - return Collections.unmodifiableMap(bossBars); - } - - public ServerProperties getServerProperties() { - return properties; - } - - public ServerConnection getServerConnection() { - return server; - } - - public Console getConsole() { - return console; - } - - public Metrics getMetrics() { - return metrics; - } - - public Set getPlayers() { - return new HashSet<>(playersByUUID.values()); - } - - public Player getPlayer(String name) { - return playersByName.get(name); - } - - public Player getPlayer(UUID uuid) { - return playersByUUID.get(uuid); - } - - public List getWorlds() { - return new ArrayList<>(worlds); - } - - public World getWorld(String name) { - for (World world : worlds) { - if (world.getName().equalsIgnoreCase(name)) { - return world; - } - } - return null; - } - - @SuppressWarnings("unchecked") - public String buildServerListResponseJson(String version, int protocol, Component motd, int maxPlayers, int playersOnline, BufferedImage favicon) throws IOException { - JSONObject json = new JSONObject(); - - JSONObject versionJson = new JSONObject(); - versionJson.put("name", version); - versionJson.put("protocol", protocol); - json.put("version", versionJson); - - JSONObject playersJson = new JSONObject(); - playersJson.put("max", maxPlayers); - playersJson.put("online", playersOnline); - json.put("players", playersJson); - - json.put("description", "%MOTD%"); - - if (favicon != null) { - if (favicon.getWidth() == 64 && favicon.getHeight() == 64) { - String base64 = "data:image/png;base64," + ImageUtils.imgToBase64String(favicon, "png"); - json.put("favicon", base64); - } else { - console.sendMessage("Server List Favicon must be 64 x 64 in size!"); - } - } - - JSONObject modInfoJson = new JSONObject(); - modInfoJson.put("type", "FML"); - modInfoJson.put("modList", new JSONArray()); - json.put("modinfo", modInfoJson); - - - TreeMap treeMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - treeMap.putAll(json); - - Gson g = new GsonBuilder().create(); - - return g.toJson(treeMap).replace("\"%MOTD%\"", GsonComponentSerializer.gson().serialize(motd)); - } - - public String buildLegacyPingResponse(String version, Component motd, int maxPlayers, int playersOnline) { - String begin = "�1"; - return String.join("\00", begin, "127", version, String.join("", Arrays.asList(motd).stream().map(each -> LegacyComponentSerializer.legacySection().serialize(each)).collect(Collectors.toList())), String.valueOf(playersOnline), String.valueOf(maxPlayers)); - } - - protected void terminate() { - isRunning.set(false); - console.sendMessage("Stopping Server..."); - - for (LimboPlugin plugin : Limbo.getInstance().getPluginManager().getPlugins()) { - try { - console.sendMessage("Disabling plugin " + plugin.getName() + " " + plugin.getInfo().getVersion()); - plugin.onDisable(); - } catch (Throwable e) { - new RuntimeException("Error while disabling " + plugin.getName() + " " + plugin.getInfo().getVersion(), e).printStackTrace(); - } - } - - tick.waitAndKillThreads(5000); - - for (Player player : getPlayers()) { - player.disconnect("Server closed"); - } - while (!getPlayers().isEmpty()) { - try { - TimeUnit.MILLISECONDS.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - console.sendMessage("Server closed"); - console.logs.close(); - } - - public void stopServer() { - System.exit(0); - } - - public boolean isRunning() { - return isRunning.get(); - } - - public int getNextEntityId() { - return entityIdCount.getAndUpdate(i -> i == Integer.MAX_VALUE ? 0 : ++i); - } - - public void dispatchCommand(CommandSender sender, String str) { - String[] command; - if (str.startsWith("/")) { - command = CustomStringUtils.splitStringToArgs(str.substring(1)); - } else { - command = CustomStringUtils.splitStringToArgs(str); - } - dispatchCommand(sender, command); - } - - public void dispatchCommand(CommandSender sender, String... args) { - try { - Limbo.getInstance().getPluginManager().fireExecutors(sender, args); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private String getLimboVersion() throws IOException { - Enumeration manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); - while (manifests.hasMoreElements()) { - URL url = manifests.nextElement(); - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - Optional line = br.lines().filter(each -> each.startsWith("Limbo-Version:")).findFirst(); - if (line.isPresent()) { - return line.get().substring(14).trim(); - } - } - } - return "Unknown"; - } - - public Inventory createInventory(Component title, int slots, InventoryHolder holder) { - return CustomInventory.create(title, slots, holder); - } - - public Inventory createInventory(InventoryType type, InventoryHolder holder) { - return createInventory(null, type, holder); - } - - public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) { - if (!type.isCreatable()) { - throw new UnsupportedOperationException("This InventoryType cannot be created."); - } - switch (type) { - case ANVIL: - return new AnvilInventory(title, holder); - default: - throw new UnsupportedOperationException("This InventoryType has not been implemented yet."); - } - } + public Inventory createInventory(Component title, InventoryType type, InventoryHolder holder) { + if (!type.isCreatable()) { + throw new UnsupportedOperationException("This InventoryType cannot be created."); + } + switch (type) { + case ANVIL: + return new AnvilInventory(title, holder); + default: + throw new UnsupportedOperationException("This InventoryType has not been implemented yet."); + } + } } diff --git a/src/main/java/com/loohp/limbo/network/ClientConnection.java b/src/main/java/com/loohp/limbo/network/ClientConnection.java index 62c89e9..485b761 100644 --- a/src/main/java/com/loohp/limbo/network/ClientConnection.java +++ b/src/main/java/com/loohp/limbo/network/ClientConnection.java @@ -41,13 +41,61 @@ import com.loohp.limbo.inventory.AnvilInventory; import com.loohp.limbo.inventory.Inventory; import com.loohp.limbo.inventory.ItemStack; import com.loohp.limbo.location.Location; -import com.loohp.limbo.network.protocol.packets.*; +import com.loohp.limbo.network.protocol.packets.ClientboundFinishConfigurationPacket; +import com.loohp.limbo.network.protocol.packets.ClientboundRegistryDataPacket; +import com.loohp.limbo.network.protocol.packets.Packet; +import com.loohp.limbo.network.protocol.packets.PacketHandshakingIn; +import com.loohp.limbo.network.protocol.packets.PacketIn; +import com.loohp.limbo.network.protocol.packets.PacketLoginInLoginStart; +import com.loohp.limbo.network.protocol.packets.PacketLoginInPluginMessaging; +import com.loohp.limbo.network.protocol.packets.PacketLoginOutDisconnect; +import com.loohp.limbo.network.protocol.packets.PacketLoginOutLoginSuccess; +import com.loohp.limbo.network.protocol.packets.PacketLoginOutPluginMessaging; +import com.loohp.limbo.network.protocol.packets.PacketOut; +import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockDig; +import com.loohp.limbo.network.protocol.packets.PacketPlayInBlockPlace; +import com.loohp.limbo.network.protocol.packets.PacketPlayInChat; +import com.loohp.limbo.network.protocol.packets.PacketPlayInCloseWindow; +import com.loohp.limbo.network.protocol.packets.PacketPlayInHeldItemChange; +import com.loohp.limbo.network.protocol.packets.PacketPlayInItemName; +import com.loohp.limbo.network.protocol.packets.PacketPlayInKeepAlive; +import com.loohp.limbo.network.protocol.packets.PacketPlayInPickItem; +import com.loohp.limbo.network.protocol.packets.PacketPlayInPluginMessaging; +import com.loohp.limbo.network.protocol.packets.PacketPlayInPosition; +import com.loohp.limbo.network.protocol.packets.PacketPlayInPositionAndLook; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameStateChange; +import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket; import com.loohp.limbo.network.protocol.packets.ServerboundResourcePackPacket.Action; +import com.loohp.limbo.network.protocol.packets.PacketPlayInRotation; +import com.loohp.limbo.network.protocol.packets.PacketPlayInSetCreativeSlot; +import com.loohp.limbo.network.protocol.packets.PacketPlayInTabComplete; +import com.loohp.limbo.network.protocol.packets.PacketPlayInUseItem; +import com.loohp.limbo.network.protocol.packets.PacketPlayInWindowClick; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutDeclareCommands; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutDisconnect; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutKeepAlive; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutLogin; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerAbilities.PlayerAbilityFlags; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoAction; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData; import com.loohp.limbo.network.protocol.packets.PacketPlayOutPlayerInfo.PlayerInfoData.PlayerInfoDataAddPlayer.PlayerSkinProperty; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutPluginMessaging; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutPositionAndLook; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnPosition; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete; import com.loohp.limbo.network.protocol.packets.PacketPlayOutTabComplete.TabCompleteMatches; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutUpdateViewPosition; +import com.loohp.limbo.network.protocol.packets.PacketStatusInPing; +import com.loohp.limbo.network.protocol.packets.PacketStatusInRequest; +import com.loohp.limbo.network.protocol.packets.PacketStatusOutPong; +import com.loohp.limbo.network.protocol.packets.PacketStatusOutResponse; +import com.loohp.limbo.network.protocol.packets.ServerboundChatCommandPacket; +import com.loohp.limbo.network.protocol.packets.ServerboundFinishConfigurationPacket; +import com.loohp.limbo.network.protocol.packets.ServerboundLoginAcknowledgedPacket; import com.loohp.limbo.player.Player; import com.loohp.limbo.player.PlayerInteractManager; import com.loohp.limbo.player.PlayerInventory; @@ -565,6 +613,10 @@ public class ClientConnection extends Thread { String str = (properties.isLogPlayerIPAddresses() ? inetAddress.getHostName() : "") + ":" + clientSocket.getPort() + "|" + player.getName() + "(" + player.getUniqueId() + ")"; Limbo.getInstance().getConsole().sendMessage("[/" + str + "] <-> Player had connected to the Limbo server!"); + PacketPlayOutGameStateChange gameEvent = new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GameStateChangeEvent.LEVEL_CHUNKS_LOAD_START, 0); + sendPacket(gameEvent); + player.playerInteractManager.update(); + PacketPlayOutDeclareCommands declare = DeclareCommands.getDeclareCommandsPacket(player); if (declare != null) { sendPacket(declare); @@ -584,7 +636,7 @@ public class ClientConnection extends Thread { Limbo.getInstance().getEventsManager().callEvent(new PlayerJoinEvent(player)); if (properties.isAllowFlight()) { - PacketPlayOutGameState state = new PacketPlayOutGameState(3, player.getGamemode().getId()); + PacketPlayOutGameStateChange state = new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GameStateChangeEvent.CHANGE_GAME_MODE, player.getGamemode().getId()); sendPacket(state); } @@ -603,13 +655,8 @@ public class ClientConnection extends Thread { // PLAYER LIST HEADER AND FOOTER CODE CONRIBUTED BY GAMERDUCK123 player.sendPlayerListHeaderAndFooter(properties.getTabHeader(), properties.getTabFooter()); - - // Start waiting for level chunks - PacketPlayOutGameEvent gameEvent = new PacketPlayOutGameEvent((byte) 13, 0); - sendPacket(gameEvent); - + ready = true; - player.playerInteractManager.update(); keepAliveTask = new TimerTask() { @Override diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameState.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameState.java deleted file mode 100644 index ab61263..0000000 --- a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameState.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of Limbo. - * - * Copyright (C) 2022. LoohpJames - * Copyright (C) 2022. Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.loohp.limbo.network.protocol.packets; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -public class PacketPlayOutGameState extends PacketOut { - - private final int reason; - private final float value; - - public PacketPlayOutGameState(int reason, float value) { - this.reason = reason; - this.value = value; - } - - public int getReason() { - return reason; - } - - public float getValue() { - return value; - } - - @Override - public byte[] serializePacket() throws IOException { - ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - - DataOutputStream output = new DataOutputStream(buffer); - output.writeByte(Packet.getPlayOut().get(getClass())); - output.writeByte(reason); - output.writeFloat(value); - - return buffer.toByteArray(); - } - -} diff --git a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameStateChange.java similarity index 55% rename from src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java rename to src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameStateChange.java index 276b414..74ab37b 100644 --- a/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameEvent.java +++ b/src/main/java/com/loohp/limbo/network/protocol/packets/PacketPlayOutGameStateChange.java @@ -1,8 +1,8 @@ /* * This file is part of Limbo. * - * Copyright (C) 2022. LoohpJames - * Copyright (C) 2022. Contributors + * Copyright (C) 2024. LoohpJames + * Copyright (C) 2024. Contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,17 +23,44 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; -public class PacketPlayOutGameEvent extends PacketOut { +public class PacketPlayOutGameStateChange extends PacketOut { - private byte event; + public enum GameStateChangeEvent { + NO_RESPAWN_BLOCK_AVAILABLE(0), + START_RAINING(1), + STOP_RAINING(2), + CHANGE_GAME_MODE(3), + WIN_GAME(4), + DEMO_EVENT(5), + ARROW_HIT_PLAYER(6), + RAIN_LEVEL_CHANGE(7), + THUNDER_LEVEL_CHANGE(8), + PUFFER_FISH_STING(9), + GUARDIAN_ELDER_EFFECT(10), + IMMEDIATE_RESPAWN(11), + LIMITED_CRAFTING(12), + LEVEL_CHUNKS_LOAD_START(13); + + private final int id; + + GameStateChangeEvent(int id) { + this.id = id; + } + + public int getId() { + return id; + } + } + + private GameStateChangeEvent event; private float value; - public PacketPlayOutGameEvent(byte event, float value) { + public PacketPlayOutGameStateChange(GameStateChangeEvent event, float value) { this.event = event; this.value = value; } - public int getEvent() { + public GameStateChangeEvent getEvent() { return event; } @@ -46,7 +73,7 @@ public class PacketPlayOutGameEvent extends PacketOut { DataOutputStream output = new DataOutputStream(buffer); output.writeByte(Packet.getPlayOut().get(getClass())); - output.writeByte(Byte.toUnsignedInt(event)); + output.writeByte(event.getId()); output.writeFloat(value); return buffer.toByteArray(); diff --git a/src/main/java/com/loohp/limbo/player/Player.java b/src/main/java/com/loohp/limbo/player/Player.java index ce2a1c8..804e33a 100644 --- a/src/main/java/com/loohp/limbo/player/Player.java +++ b/src/main/java/com/loohp/limbo/player/Player.java @@ -45,7 +45,7 @@ import com.loohp.limbo.network.protocol.packets.ClientboundSetTitlesAnimationPac import com.loohp.limbo.network.protocol.packets.ClientboundSystemChatPacket; import com.loohp.limbo.network.protocol.packets.PacketOut; import com.loohp.limbo.network.protocol.packets.PacketPlayOutCloseWindow; -import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameState; +import com.loohp.limbo.network.protocol.packets.PacketPlayOutGameStateChange; import com.loohp.limbo.network.protocol.packets.PacketPlayOutHeldItemChange; import com.loohp.limbo.network.protocol.packets.PacketPlayOutNamedSoundEffect; import com.loohp.limbo.network.protocol.packets.PacketPlayOutOpenWindow; @@ -151,7 +151,7 @@ public class Player extends LivingEntity implements CommandSender, InventoryHold public void setGamemode(GameMode gamemode) { if (!this.gamemode.equals(gamemode)) { try { - PacketPlayOutGameState state = new PacketPlayOutGameState(3, gamemode.getId()); + PacketPlayOutGameStateChange state = new PacketPlayOutGameStateChange(PacketPlayOutGameStateChange.GameStateChangeEvent.CHANGE_GAME_MODE, gamemode.getId()); clientConnection.sendPacket(state); } catch (IOException e) { e.printStackTrace(); diff --git a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java index 9497770..9c57313 100644 --- a/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java +++ b/src/main/java/com/loohp/limbo/player/PlayerInteractManager.java @@ -30,7 +30,6 @@ import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityDestroy; import com.loohp.limbo.network.protocol.packets.PacketPlayOutEntityMetadata; import com.loohp.limbo.network.protocol.packets.PacketPlayOutSpawnEntity; import com.loohp.limbo.network.protocol.packets.PacketPlayOutUnloadChunk; -import com.loohp.limbo.utils.GameMode; import com.loohp.limbo.world.ChunkPosition; import com.loohp.limbo.world.World; import net.querz.mca.Chunk; @@ -47,131 +46,118 @@ import java.util.Set; import java.util.stream.Collectors; public class PlayerInteractManager { + + private Player player; + + private Set entities; + private Map currentViewing; + + public PlayerInteractManager() { + this.player = null; + this.entities = new HashSet<>(); + this.currentViewing = new HashMap<>(); + } + + protected void setPlayer(Player player) { + if (this.player == null) { + this.player = player; + } else { + throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created"); + } + } + + public Player getPlayer() { + return player; + } - private Player player; + public void update() throws IOException { + if (player.clientConnection.getClientState() != ClientConnection.ClientState.PLAY) { + return; + } - private Set entities; - private Map currentViewing; - private final Map chunkUpdates; + int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance(); + int viewDistanceBlocks = viewDistanceChunks << 4; + Location location = player.getLocation(); + Set entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet()); + for (Entity entity : entitiesInRange) { + if (!entities.contains(entity)) { + PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), 0, (short) 0, (short) 0, (short) 0); + player.clientConnection.sendPacket(packet); - public PlayerInteractManager() { - this.player = null; - this.entities = new HashSet<>(); - this.currentViewing = new HashMap<>(); - this.chunkUpdates = new HashMap<>(); - } + PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity); + player.clientConnection.sendPacket(meta); + } + } + List ids = new ArrayList<>(); + for (Entity entity : entities) { + if (!entitiesInRange.contains(entity)) { + ids.add(entity.getEntityId()); + } + } + for (int id : ids) { + PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(id); + player.clientConnection.sendPacket(packet); + } - protected void setPlayer(Player player) { - if (this.player == null) { - this.player = player; - } else { - throw new RuntimeException("Player in PlayerInteractManager cannot be changed once created"); - } - } + entities = entitiesInRange; - public Player getPlayer() { - return player; - } + int playerChunkX = (int) location.getX() >> 4; + int playerChunkZ = (int) location.getZ() >> 4; + World world = location.getWorld(); - public void update() throws IOException { - if (player.clientConnection.getClientState() != ClientConnection.ClientState.PLAY && !player.clientConnection.isReady()) { - return; - } + Map chunksInRange = new HashMap<>(); - int viewDistanceChunks = Limbo.getInstance().getServerProperties().getViewDistance(); - int viewDistanceBlocks = viewDistanceChunks << 4; - Location location = player.getLocation(); - Set entitiesInRange = player.getWorld().getEntities().stream().filter(each -> each.getLocation().distanceSquared(location) < viewDistanceBlocks * viewDistanceBlocks).collect(Collectors.toSet()); - for (Entity entity : entitiesInRange) { - if (!entities.contains(entity)) { - PacketPlayOutSpawnEntity packet = new PacketPlayOutSpawnEntity(entity.getEntityId(), entity.getUniqueId(), entity.getType(), entity.getX(), entity.getY(), entity.getZ(), entity.getYaw(), entity.getPitch(), entity.getPitch(), 0, (short) 0, (short) 0, (short) 0); - player.clientConnection.sendPacket(packet); + for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) { + for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) { + Chunk chunk = world.getChunkAt(x, z); + if (chunk != null) { + chunksInRange.put(new ChunkPosition(world, x, z), chunk); + } else { + chunksInRange.put(new ChunkPosition(world, x, z), World.EMPTY_CHUNK); + } + } + } - PacketPlayOutEntityMetadata meta = new PacketPlayOutEntityMetadata(entity); - player.clientConnection.sendPacket(meta); - } - } - List ids = new ArrayList<>(); - for (Entity entity : entities) { - if (!entitiesInRange.contains(entity)) { - ids.add(entity.getEntityId()); - } - } - for (int id : ids) { - PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(id); - player.clientConnection.sendPacket(packet); - } + for (Entry entry : currentViewing.entrySet()) { + ChunkPosition chunkPos = entry.getKey(); + if (!chunksInRange.containsKey(chunkPos)) { + PacketPlayOutUnloadChunk packet = new PacketPlayOutUnloadChunk(chunkPos.getChunkX(), chunkPos.getChunkZ()); + player.clientConnection.sendPacket(packet); + } + } - entities = entitiesInRange; - - int playerChunkX = (int) location.getX() >> 4; - int playerChunkZ = (int) location.getZ() >> 4; - World world = location.getWorld(); - - Map chunksInRange = new HashMap<>(); - - for (int x = playerChunkX - viewDistanceChunks; x < playerChunkX + viewDistanceChunks; x++) { - for (int z = playerChunkZ - viewDistanceChunks; z < playerChunkZ + viewDistanceChunks; z++) { - Chunk chunk = world.getChunkAt(x, z); - if (chunk != null) { - chunksInRange.put(new ChunkPosition(world, x, z), chunk); + int counter = 0; + ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket(); + player.clientConnection.sendPacket(chunkBatchStartPacket); + for (Entry entry : chunksInRange.entrySet()) { + ChunkPosition chunkPos = entry.getKey(); + if (!currentViewing.containsKey(chunkPos)) { + Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); + if (chunk == null) { + ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList()); + player.clientConnection.sendPacket(chunkdata); } else { - chunksInRange.put(new ChunkPosition(world, x, z), World.EMPTY_CHUNK); + List blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); + if (blockChunk == null) { + blockChunk = new ArrayList<>(); + } + List skyChunk = null; + if (world.hasSkyLight()) { + skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); + } + if (skyChunk == null) { + skyChunk = new ArrayList<>(); + } + ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk); + player.clientConnection.sendPacket(chunkdata); } + counter++; } - } + } + ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter); + player.clientConnection.sendPacket(chunkBatchFinishedPacket); - for (ChunkPosition chunkPos : currentViewing.keySet()) { - if (!chunksInRange.containsKey(chunkPos)) { - PacketPlayOutUnloadChunk packet = new PacketPlayOutUnloadChunk(chunkPos.getChunkX(), chunkPos.getChunkZ()); - player.clientConnection.sendPacket(packet); - } - } - - // add chunk candidates for updating - chunkUpdates.clear(); - chunkUpdates.putAll(chunksInRange); - - // blocks cannot be broken, so once we've sent all of them, don't update them anymore - if (getPlayer().getGamemode() == GameMode.ADVENTURE) { - for (ChunkPosition chunkPos : currentViewing.keySet()) { - chunkUpdates.remove(chunkPos); - } - } - - // if we don't have any chunk updates, don't send any packets - if (chunkUpdates.isEmpty()) return; - - int counter = 0; - ClientboundChunkBatchStartPacket chunkBatchStartPacket = new ClientboundChunkBatchStartPacket(); - player.clientConnection.sendPacket(chunkBatchStartPacket); - for (Entry entry : chunkUpdates.entrySet()) { - ChunkPosition chunkPos = entry.getKey(); - Chunk chunk = chunkPos.getWorld().getChunkAt(chunkPos.getChunkX(), chunkPos.getChunkZ()); - if (chunk == null) { - ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), entry.getValue(), world.getEnvironment(), Collections.emptyList(), Collections.emptyList()); - player.clientConnection.sendPacket(chunkdata); - } else { - List blockChunk = world.getLightEngineBlock().getBlockLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); - if (blockChunk == null) { - blockChunk = new ArrayList<>(); - } - List skyChunk = null; - if (world.hasSkyLight()) { - skyChunk = world.getLightEngineSky().getSkyLightBitMask(chunkPos.getChunkX(), chunkPos.getChunkZ()); - } - if (skyChunk == null) { - skyChunk = new ArrayList<>(); - } - ClientboundLevelChunkWithLightPacket chunkdata = new ClientboundLevelChunkWithLightPacket(chunkPos.getChunkX(), chunkPos.getChunkZ(), chunk, world.getEnvironment(), skyChunk, blockChunk); - player.clientConnection.sendPacket(chunkdata); - } - counter++; - } - ClientboundChunkBatchFinishedPacket chunkBatchFinishedPacket = new ClientboundChunkBatchFinishedPacket(counter); - player.clientConnection.sendPacket(chunkBatchFinishedPacket); - - currentViewing = chunksInRange; - } + currentViewing = chunksInRange; + } } diff --git a/src/main/java/com/loohp/limbo/registry/Registry.java b/src/main/java/com/loohp/limbo/registry/Registry.java index a9086e5..72dab8a 100644 --- a/src/main/java/com/loohp/limbo/registry/Registry.java +++ b/src/main/java/com/loohp/limbo/registry/Registry.java @@ -48,20 +48,17 @@ public class Registry { static { String name = "registries.json"; - File file = new File(Limbo.getInstance().getInternalDataFolder(), name); - if (!file.exists()) { - try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(name)) { - Files.copy(in, file.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } Map blockEntityType = new HashMap<>(); Key defaultItemKey = null; BiMap itemIds = HashBiMap.create(); Map menuIds = new HashMap<>(); - try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { + + InputStream inputStream = Limbo.class.getClassLoader().getResourceAsStream(name); + if (inputStream == null) { + throw new RuntimeException("Failed to load " + name + " from jar!"); + } + try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { JSONObject json = (JSONObject) new JSONParser().parse(reader); JSONObject blockEntityJson = (JSONObject) ((JSONObject) json.get("minecraft:block_entity_type")).get("entries"); diff --git a/src/main/java/com/loohp/limbo/world/DimensionRegistry.java b/src/main/java/com/loohp/limbo/world/DimensionRegistry.java index 323bf7e..c1480a6 100644 --- a/src/main/java/com/loohp/limbo/world/DimensionRegistry.java +++ b/src/main/java/com/loohp/limbo/world/DimensionRegistry.java @@ -37,24 +37,16 @@ public class DimensionRegistry { private CompoundTag defaultTag; private CompoundTag codec; - private File reg; public DimensionRegistry() { this.defaultTag = new CompoundTag(); - String name = "dimension_registry.json"; - File file = new File(Limbo.getInstance().getInternalDataFolder(), name); - if (!file.exists()) { - try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(name)) { - Files.copy(in, file.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - this.reg = file; - - try (InputStreamReader reader = new InputStreamReader(Files.newInputStream(reg.toPath()), StandardCharsets.UTF_8)) { + + InputStream inputStream = Limbo.class.getClassLoader().getResourceAsStream(name); + if (inputStream == null) { + throw new RuntimeException("Failed to load " + name + " from jar!"); + } + try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { JSONObject json = (JSONObject) new JSONParser().parse(reader); CompoundTag tag = CustomNBTUtils.getCompoundTagFromJson((JSONObject) json.get("value")); defaultTag = tag; @@ -64,10 +56,6 @@ public class DimensionRegistry { } } - public File getFile() { - return reg; - } - public void resetCodec() { codec = defaultTag.clone(); } diff --git a/src/main/java/com/loohp/limbo/world/GeneratedBlockDataMappings.java b/src/main/java/com/loohp/limbo/world/GeneratedBlockDataMappings.java index 4375327..e9dd234 100644 --- a/src/main/java/com/loohp/limbo/world/GeneratedBlockDataMappings.java +++ b/src/main/java/com/loohp/limbo/world/GeneratedBlockDataMappings.java @@ -30,6 +30,8 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.util.HashMap; import java.util.Map; @@ -41,17 +43,12 @@ public class GeneratedBlockDataMappings { static { String block = "blocks.json"; - File file = new File(Limbo.getInstance().getInternalDataFolder(), block); - if (!file.exists()) { - try (InputStream in = Limbo.class.getClassLoader().getResourceAsStream(block)) { - Files.copy(in, file.toPath()); - } catch (IOException e) { - e.printStackTrace(); - } - } - - try { - globalPalette = (JSONObject) new JSONParser().parse(new FileReader(file)); + InputStream inputStream = Limbo.class.getClassLoader().getResourceAsStream(block); + if (inputStream == null) { + throw new RuntimeException("Failed to load " + block + " from jar!"); + } + try (InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + globalPalette = (JSONObject) new JSONParser().parse(reader); } catch (IOException | ParseException e) { e.printStackTrace(); } diff --git a/src/main/resources/mapping.json b/src/main/resources/mapping.json index a9c649a..365a148 100644 --- a/src/main/resources/mapping.json +++ b/src/main/resources/mapping.json @@ -43,12 +43,12 @@ "PacketPlayOutLogin": "0x29", "PacketPlayOutPositionAndLook": "0x3E", "PacketPlayOutSpawnPosition": "0x54", - "PacketPlayOutGameEvent": "0x20", "ClientboundSystemChatPacket": "0x69", "PacketPlayOutPlayerAbilities": "0x36", "ClientboundLevelChunkWithLightPacket": "0x25", "PacketPlayOutUnloadChunk": "0x1F", "PacketPlayOutKeepAlive": "0x15", + "PacketPlayOutGameStateChange": "0x20", "PacketPlayOutPlayerInfo": "0x3C", "PacketPlayOutUpdateViewPosition": "0x52", "PacketPlayOutDisconnect": "0x1B", @@ -56,7 +56,6 @@ "PacketPlayOutTabComplete": "0x10", "PacketPlayOutDeclareCommands": "0x11", "PacketPlayOutRespawn": "0x45", - "PacketPlayOutGameState": "0x20", "PacketPlayOutEntityDestroy": "0x40", "PacketPlayOutEntityMetadata": "0x56", "PacketPlayOutSpawnEntity": "0x01", @@ -87,4 +86,4 @@ "PacketStatusOutResponse": "0x00", "PacketStatusOutPong": "0x01" } -} +} \ No newline at end of file