Elytrium / LimboAPI

An API which provides virtual servers features to Velocity
https://elytrium.net/
GNU Affero General Public License v3.0
234 stars 63 forks source link

[BUG] Block entity IDs are loaded incorrectly #157

Closed metabrixkt closed 2 months ago

metabrixkt commented 2 months ago

Description

When block entity IDs are loaded from /mapping/blockentities_mapping.json, only legacy and 1.19 block entity versions are recognized properly, all other versions fall back to BlockEntityVersion.LEGACY. This happens because of incorrect conditions in BlockEntityVersion#parse(...) for any block entity that doesn't exist in 1.19.

Steps to reproduce

  1. Create a VirtualWorld that contains blocks that doesn't exist in 1.19
  2. Create a Limbo from this world
  3. See NullPointerException in SimpleBlockEntity#getID(BlockEntityVersion)

What happens

Using minecraft:hanging_sign block entity as an example

Loading block entity mappings:

  1. minecraft:hanging_sign mappings are loaded as Map<String, Map<String, Integer>>: there are mappings for legacy version and for 1.19.3-1.21 versions
  2. For each version...
    1. Version is parsed into BlockEntityVersion using its parse method
    2. legacy -> LEGACY, but 1.19.3-1.21 are also parsed into LEGACY because none of them literally matches 1.19, falling back to the default branch in the switch statement
  3. Imported mappings now look like [legacy -> 8] with no other mappings

When getting the block entity ID for a protocol version (for 1.19+):

  1. ProtocolVersion is properly translated into BlockEntityVersion.MINECRAFT_1_19
  2. SimpleBlockEntity#getID(BlockEntityVersion) returns a null mapping for this version, since it only has a mapping for legacy version, resulting in NPE when unboxing Integer into int

Expected behavior

All versions greater than or equal to 1.19 are parsed into BlockEntityVersion.MINECRAFT_1_19 in BlockEntityVersion#parse(...)

Proposed fix

I think there's a better way to parse the version, but you get the point:

diff --git a/api/src/main/java/net/elytrium/limboapi/api/chunk/BlockEntityVersion.java b/api/src/main/java/net/elytrium/limboapi/api/chunk/BlockEntityVersion.java
index 27c6351..7c6e755 100644
--- a/api/src/main/java/net/elytrium/limboapi/api/chunk/BlockEntityVersion.java
+++ b/api/src/main/java/net/elytrium/limboapi/api/chunk/BlockEntityVersion.java
@@ -46,10 +46,14 @@ public enum BlockEntityVersion {
   }

   public static BlockEntityVersion parse(String from) {
-    return switch (from) {
-      case "1.19" -> MINECRAFT_1_19;
-      default -> LEGACY;
-    };
+    String[] parts = from.split("\\.");
+    if (parts.length >= 2) {
+      try {
+        if (Integer.parseInt(parts[1]) >= 19) return MINECRAFT_1_19;
+      } catch (NumberFormatException ignored) {}
+    }
+
+    return LEGACY;
   }

   public static BlockEntityVersion from(ProtocolVersion protocolVersion) {

Server Info: