From 6ab71e750a02b458bf9e4d65e7de8e0d3b28ddd7 Mon Sep 17 00:00:00 2001 From: HotWaterFlask <104620825+HotWaterFlask@users.noreply.github.com> Date: Wed, 26 Aug 2026 22:32:18 +0800 Subject: [PATCH 1/4] Add files via upload --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index e4267cba..213ee0c7 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.github.yuttyann ScriptBlockPlus - 2.3.4 + 2.3.5 ScriptBlockPlus https://github.com/yuttyann/ScriptBlockPlus From e9ac5ae0727cf65585878f754237401e6c1387ea Mon Sep 17 00:00:00 2001 From: HotWaterFlask <104620825+HotWaterFlask@users.noreply.github.com> Date: Wed, 26 Aug 2026 22:34:35 +0800 Subject: [PATCH 2/4] 26.2support Minecraft 26.2 version support --- .../utils/version/Version.java | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/yuttyann/scriptblockplus/utils/version/Version.java b/src/main/java/com/github/yuttyann/scriptblockplus/utils/version/Version.java index 4848a90a..41de4ec1 100644 --- a/src/main/java/com/github/yuttyann/scriptblockplus/utils/version/Version.java +++ b/src/main/java/com/github/yuttyann/scriptblockplus/utils/version/Version.java @@ -54,8 +54,25 @@ public static Version of(@NotNull String version) { if (dot1 < 0) { throw new IllegalArgumentException("Invalid Version: " + version); } - int part1 = parseInt(version, 0, dot1, 10), part2 = parseInt(version, dot1 + 1, dot2 < 0 ? version.length() : dot2, 10); - return of(part1, part2, dot2 >= 0 ? parseInt(version, dot2 + 1, version.length(), 10) : 0, qualifier); + int part1 = parseLeadingInt(version, 0, dot1); + int part2 = parseLeadingInt(version, dot1 + 1, dot2 < 0 ? version.length() : dot2); + int part3 = dot2 >= 0 ? parseLeadingInt(version, dot2 + 1, version.length()) : 0; + return of(part1, part2, part3, qualifier); + } + + /** + * 文字列の先頭から連続する数字を抽出して int に変換します。 + * 数字が1つも無い場合は0を返します。 + */ + private static int parseLeadingInt(@NotNull String s, int start, int end) { + int actualEnd = start; + while (actualEnd < end && Character.isDigit(s.charAt(actualEnd))) { + actualEnd++; + } + if (actualEnd == start) { + return 0; + } + return parseInt(s, start, actualEnd, 10); } @NotNull From 841d802d2c49c67cb618658c0b1ad9238bfbf121 Mon Sep 17 00:00:00 2001 From: HotWaterFlask <104620825+HotWaterFlask@users.noreply.github.com> Date: Wed, 26 Aug 2026 23:43:31 +0800 Subject: [PATCH 3/4] =?UTF-8?q?Paper=2026.2=EF=BC=88Minecraft=20"Chaos=20C?= =?UTF-8?q?ubed"=20=E6=9B=B4=E6=96=B0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复内容(3 个文件) NetMinecraft.java#L305-L306 — 新增枚举: Java /** {@code net.minecraft.world.entity.monster.cubemob} */ WORLD_ENTITY_MONSTER_CUBEMOB(WORLD_ENTITY_MONSTER, "cubemob"), PaperRemappedAccessor_v1_21_6.java#L66-L77 — 新增 getMagmaCubeClass() 辅助方法,优先尝试旧包,失败后 fallback 到 cubemob 新包;两处 WORLD_ENTITY_MONSTER.getClass("MagmaCube") 替换为 getMagmaCubeClass() PaperRemappedAccessorLegacy.java#L65-L76 — 同样的 fallback 处理 兼容性说明 GlowEntity(ScriptViewer 发光可视化)使用 Bukkit API 的 org.bukkit.entity.MagmaCube,该接口在 26.2 中依然存在(setSize 从 Slime 移到 AbstractCubeMob),无需修改 旧版本(≤1.21.x)会命中 WORLD_ENTITY_MONSTER 路径,新版本(26.2+)命中 cubemob 路径,两者兼容 --- .../utils/server/NetMinecraft.java | 2 ++ .../minecraft/PaperRemappedAccessorLegacy.java | 17 +++++++++++++++-- .../PaperRemappedAccessor_v1_21_6.java | 17 +++++++++++++++-- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/NetMinecraft.java b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/NetMinecraft.java index 5dfd509b..b85b9fcb 100644 --- a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/NetMinecraft.java +++ b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/NetMinecraft.java @@ -302,6 +302,8 @@ public enum NetMinecraft implements SimpleReflection { WORLD_ENTITY_ITEM(WORLD_ENTITY, "item"), /** {@code net.minecraft.world.entity.monster} */ WORLD_ENTITY_MONSTER(WORLD_ENTITY, "monster"), + /** {@code net.minecraft.world.entity.monster.cubemob} */ + WORLD_ENTITY_MONSTER_CUBEMOB(WORLD_ENTITY_MONSTER, "cubemob"), /** {@code net.minecraft.world.entity.monster.breeze} */ WORLD_ENTITY_MONSTER_BREEZE(WORLD_ENTITY_MONSTER, "breeze"), /** {@code net.minecraft.world.entity.monster.hoglin} */ diff --git a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java index 0bc86c1e..c695442c 100644 --- a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java +++ b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java @@ -62,6 +62,19 @@ public class PaperRemappedAccessorLegacy implements NativeAccessor { private final Object blockPosZero; private final Object magmaCubeType; + /** + * ゲームバージョンに応じた MagmaCube クラスを取得します。 + *

+ * 26.2 以降は {@code net.minecraft.world.entity.monster.cubemob} パッケージに移動されました。 + */ + private static Class getMagmaCubeClass() { + try { + return WORLD_ENTITY_MONSTER.getClass("MagmaCube"); + } catch (IllegalArgumentException e) { + return WORLD_ENTITY_MONSTER_CUBEMOB.getClass("MagmaCube"); + } + } + PaperRemappedAccessorLegacy() throws ReflectiveOperationException { // sendPacket field(SERVER_LEVEL.getClass("ServerPlayer")) @@ -257,13 +270,13 @@ public class PaperRemappedAccessorLegacy implements NativeAccessor { .findFirst("ContainerMenu.checkReachable"); // newMagmaCube - construct(WORLD_ENTITY_MONSTER.getClass("MagmaCube")) + construct(getMagmaCubeClass()) .parameterTypes(WORLD_ENTITY.getClass("EntityType"), WORLD_LEVEL.getClass("Level")) .findFirst("MagmaCube"); // newCraftMagmaCube construct(ENTITY.getClass("CraftMagmaCube")) - .parameterTypes(CRAFTBUKKIT.getClass("CraftServer"), WORLD_ENTITY_MONSTER.getClass("MagmaCube")) + .parameterTypes(CRAFTBUKKIT.getClass("CraftServer"), getMagmaCubeClass()) .findFirst("CraftMagmaCube"); // newClientboundSetEntityDataPacket diff --git a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java index 33703bc0..42bc2ecb 100644 --- a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java +++ b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java @@ -63,6 +63,19 @@ public class PaperRemappedAccessor_v1_21_6 implements NativeAccessor { private final Object blockPosZero; private final Object magmaCubeType; + /** + * ゲームバージョンに応じた MagmaCube クラスを取得します。 + *

+ * 26.2 以降は {@code net.minecraft.world.entity.monster.cubemob} パッケージに移動されました。 + */ + private static Class getMagmaCubeClass() { + try { + return WORLD_ENTITY_MONSTER.getClass("MagmaCube"); + } catch (IllegalArgumentException e) { + return WORLD_ENTITY_MONSTER_CUBEMOB.getClass("MagmaCube"); + } + } + PaperRemappedAccessor_v1_21_6() throws ReflectiveOperationException { // sendPacket field(SERVER_LEVEL.getClass("ServerPlayer")) @@ -258,13 +271,13 @@ public class PaperRemappedAccessor_v1_21_6 implements NativeAccessor { .findFirst("ContainerMenu.checkReachable"); // newMagmaCube - construct(WORLD_ENTITY_MONSTER.getClass("MagmaCube")) + construct(getMagmaCubeClass()) .parameterTypes(WORLD_ENTITY.getClass("EntityType"), WORLD_LEVEL.getClass("Level")) .findFirst("MagmaCube"); // newCraftMagmaCube construct(ENTITY.getClass("CraftMagmaCube")) - .parameterTypes(CRAFTBUKKIT.getClass("CraftServer"), WORLD_ENTITY_MONSTER.getClass("MagmaCube")) + .parameterTypes(CRAFTBUKKIT.getClass("CraftServer"), getMagmaCubeClass()) .findFirst("CraftMagmaCube"); // newClientboundSetEntityDataPacket From 148ae241fdc9f97e0b576fd58f857266da9f1180 Mon Sep 17 00:00:00 2001 From: HotWaterFlask <104620825+HotWaterFlask@users.noreply.github.com> Date: Thu, 27 Aug 2026 00:08:30 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E4=BF=AE=E5=A4=8D26.2=20=E4=B8=AD=20net.mi?= =?UTF-8?q?necraft.resources.ResourceLocation=20=E5=B7=B2=E8=A2=AB?= =?UTF-8?q?=E9=87=8D=E5=91=BD=E5=90=8D=E4=B8=BA=20net.minecraft.resources.?= =?UTF-8?q?Identifier=EF=BC=88MC=201.21.11=20=E8=B5=B7=E7=9A=84=E5=85=A8?= =?UTF-8?q?=E5=B1=80=E6=94=B9=E5=90=8D=EF=BC=89=EF=BC=8C=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E6=96=B9=E6=A1=88=202=20=E5=8F=8D=E5=B0=84=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新 PaperRemappedAccessor_v1_21_6.java#L350-L365 和 PaperRemappedAccessorLegacy.java#L349-L364: Java // 先尝试 Identifier(1.21.11+ / 26.x) identifierClass = Utils.getClassForName("net.minecraft.resources.Identifier"); // 失败再回退 ResourceLocation(1.21.10 及更早) 现在的完整 fallback 链 EntityType.MAGMA_CUBE 静态字段(≤1.21.10) BuiltInRegistries.ENTITY_TYPE.getValue(Identifier.parse("minecraft:magma_cube"))(26.x,Identifier) BuiltInRegistries.ENTITY_TYPE.getValue(ResourceLocation.parse(...))(1.21.11 前兜底) CraftEntityType.bukkitToMinecraft(EntityType.MAGMA_CUBE)(CraftBukkit 桥接兜底) --- .../PaperRemappedAccessorLegacy.java | 43 ++++++++++++++++++- .../PaperRemappedAccessor_v1_21_6.java | 43 ++++++++++++++++++- 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java index c695442c..9c625955 100644 --- a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java +++ b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessorLegacy.java @@ -26,6 +26,7 @@ import static org.apache.commons.lang3.ArrayUtils.*; import static org.apache.commons.lang3.math.NumberUtils.*; +import java.lang.reflect.InvocationTargetException; import java.util.List; import org.bukkit.Bukkit; @@ -328,10 +329,50 @@ private static Class getMagmaCubeClass() { this.m = methods(); this.c = constructs(); this.blockPosZero = c.newInstance("BlockPos", INT_ARRAY_ZERO_3); - this.magmaCubeType = field(WORLD_ENTITY.getClass("EntityType")).modifiers(STATIC).name("MAGMA_CUBE").fieldType(WORLD_ENTITY.getClass("EntityType")).findFirst().get(null); + this.magmaCubeType = getMagmaCubeType(); this.unknownReason = Enum.valueOf((Class) Utils.getClassForName("org.bukkit.event.inventory.InventoryCloseEvent$Reason"), "UNKNOWN"); } + /** + * ゲームバージョンに応じた MagmaCube の {@code EntityType} を取得します。 + *

+ * 26.x では {@code EntityType.MAGMA_CUBE} の静的フィールドが廃止され、 + * {@code BuiltInRegistries.ENTITY_TYPE} のレジストリから取得する必要があります。 + */ + private static Object getMagmaCubeType() throws ReflectiveOperationException { + // 1. EntityType.MAGMA_CUBE 静的フィールド(1.21.x 以前) + try { + return field(WORLD_ENTITY.getClass("EntityType")).modifiers(STATIC).name("MAGMA_CUBE") + .fieldType(WORLD_ENTITY.getClass("EntityType")).findFirst().get(null); + } catch (NullPointerException ignored) { } + + // 2. BuiltInRegistries.ENTITY_TYPE レジストリから取得(1.21.11+ / 26.x) + try { + var builtInRegistriesClass = Utils.getClassForName("net.minecraft.core.registries.BuiltInRegistries"); + var registry = builtInRegistriesClass.getField("ENTITY_TYPE").get(null); + Class identifierClass; + try { + // 1.21.11 以降は ResourceLocation が Identifier に改名された + identifierClass = Utils.getClassForName("net.minecraft.resources.Identifier"); + } catch (IllegalArgumentException ignored) { + identifierClass = Utils.getClassForName("net.minecraft.resources.ResourceLocation"); + } + var parseMethod = identifierClass.getMethod("parse", String.class); + var magmaCubeKey = parseMethod.invoke(null, "minecraft:magma_cube"); + var getValueMethod = registry.getClass().getMethod("getValue", identifierClass); + return getValueMethod.invoke(registry, magmaCubeKey); + } catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException ignored) { } + + // 3. CraftEntityType.bukkitToMinecraft から取得 + try { + var craftEntityTypeClass = Utils.getClassForName("org.bukkit.craftbukkit.entity.CraftEntityType"); + var bukkitToMinecraft = craftEntityTypeClass.getMethod("bukkitToMinecraft", org.bukkit.entity.EntityType.class); + return bukkitToMinecraft.invoke(null, org.bukkit.entity.EntityType.MAGMA_CUBE); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { } + + throw new ReflectiveOperationException("Could not resolve EntityType for MagmaCube"); + } + @Override public void sendAllPacket(@NotNull Object packet) throws ReflectiveOperationException { var temp = new Object[] { packet }; diff --git a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java index 42bc2ecb..4ba1eede 100644 --- a/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java +++ b/src/main/java/com/github/yuttyann/scriptblockplus/utils/server/minecraft/PaperRemappedAccessor_v1_21_6.java @@ -26,6 +26,7 @@ import static org.apache.commons.lang3.ArrayUtils.*; import static org.apache.commons.lang3.math.NumberUtils.*; +import java.lang.reflect.InvocationTargetException; import java.util.List; import org.bukkit.Bukkit; @@ -329,10 +330,50 @@ private static Class getMagmaCubeClass() { this.m = methods(); this.c = constructs(); this.blockPosZero = c.newInstance("BlockPos", INT_ARRAY_ZERO_3); - this.magmaCubeType = field(WORLD_ENTITY.getClass("EntityType")).modifiers(STATIC).name("MAGMA_CUBE").fieldType(WORLD_ENTITY.getClass("EntityType")).findFirst().get(null); + this.magmaCubeType = getMagmaCubeType(); this.unknownReason = Enum.valueOf((Class) Utils.getClassForName("org.bukkit.event.inventory.InventoryCloseEvent$Reason"), "UNKNOWN"); } + /** + * ゲームバージョンに応じた MagmaCube の {@code EntityType} を取得します。 + *

+ * 26.x では {@code EntityType.MAGMA_CUBE} の静的フィールドが廃止され、 + * {@code BuiltInRegistries.ENTITY_TYPE} のレジストリから取得する必要があります。 + */ + private static Object getMagmaCubeType() throws ReflectiveOperationException { + // 1. EntityType.MAGMA_CUBE 静的フィールド(1.21.x 以前) + try { + return field(WORLD_ENTITY.getClass("EntityType")).modifiers(STATIC).name("MAGMA_CUBE") + .fieldType(WORLD_ENTITY.getClass("EntityType")).findFirst().get(null); + } catch (NullPointerException ignored) { } + + // 2. BuiltInRegistries.ENTITY_TYPE レジストリから取得(1.21.11+ / 26.x) + try { + var builtInRegistriesClass = Utils.getClassForName("net.minecraft.core.registries.BuiltInRegistries"); + var registry = builtInRegistriesClass.getField("ENTITY_TYPE").get(null); + Class identifierClass; + try { + // 1.21.11 以降は ResourceLocation が Identifier に改名された + identifierClass = Utils.getClassForName("net.minecraft.resources.Identifier"); + } catch (IllegalArgumentException ignored) { + identifierClass = Utils.getClassForName("net.minecraft.resources.ResourceLocation"); + } + var parseMethod = identifierClass.getMethod("parse", String.class); + var magmaCubeKey = parseMethod.invoke(null, "minecraft:magma_cube"); + var getValueMethod = registry.getClass().getMethod("getValue", identifierClass); + return getValueMethod.invoke(registry, magmaCubeKey); + } catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException | InvocationTargetException ignored) { } + + // 3. CraftEntityType.bukkitToMinecraft から取得 + try { + var craftEntityTypeClass = Utils.getClassForName("org.bukkit.craftbukkit.entity.CraftEntityType"); + var bukkitToMinecraft = craftEntityTypeClass.getMethod("bukkitToMinecraft", org.bukkit.entity.EntityType.class); + return bukkitToMinecraft.invoke(null, org.bukkit.entity.EntityType.MAGMA_CUBE); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) { } + + throw new ReflectiveOperationException("Could not resolve EntityType for MagmaCube"); + } + @Override public void sendAllPacket(@NotNull Object packet) throws ReflectiveOperationException { var temp = new Object[] { packet };