From 91e4bc5b9a45f1395680d832d1a0727a3e1c4f03 Mon Sep 17 00:00:00 2001 From: jens Date: Sat, 4 Jul 2026 17:32:41 +0200 Subject: [PATCH 1/2] Fix EnderDragon NPC ticking on Paper 26.2 Use EnderDragon#getSubEntities() in the v26_2_R1 controller instead of directly accessing EnderDragon.subEntities. Paper 26.2 keeps that field private at runtime, which caused an IllegalAccessError when EnderDragon NPCs ticked. --- .../nms/v26_2_R1/entity/EnderDragonController.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/entity/EnderDragonController.java b/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/entity/EnderDragonController.java index 5330e2e21..ff21c5384 100644 --- a/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/entity/EnderDragonController.java +++ b/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/entity/EnderDragonController.java @@ -25,6 +25,7 @@ import net.minecraft.world.entity.MoverType; import net.minecraft.world.entity.boss.enderdragon.DragonFlightHistory.Sample; import net.minecraft.world.entity.boss.enderdragon.EnderDragon; +import net.minecraft.world.entity.boss.enderdragon.EnderDragonPart; import net.minecraft.world.entity.boss.enderdragon.phases.EnderDragonPhase; import net.minecraft.world.entity.vehicle.boat.AbstractBoat; import net.minecraft.world.entity.vehicle.minecart.AbstractMinecart; @@ -86,9 +87,9 @@ public void aiStep() { new double[][] { toa(flightHistory.get(0, 1F)), toa(flightHistory.get(5, 1F)), toa(flightHistory.get(10, 1F)), toa(flightHistory.get(12, 1F)), toa(flightHistory.get(14, 1F)), toa(flightHistory.get(16, 1F)) }); + EnderDragonPart[] subEntities = getSubEntities(); for (int j = 0; j < subEntities.length; ++j) { - Vec3 vec3 = new Vec3(this.subEntities[j].getX(), this.subEntities[j].getY(), - this.subEntities[j].getZ()); + Vec3 vec3 = new Vec3(subEntities[j].getX(), subEntities[j].getY(), subEntities[j].getZ()); subEntities[j].setPos(this.getX() + pos[j][0], this.getY() + pos[j][1], this.getZ() + pos[j][2]); subEntities[j].xo = subEntities[j].xOld = vec3.x; subEntities[j].yo = subEntities[j].yOld = vec3.y; From 67dfe08e3023ae46a9df53cb83cf727cb35613db Mon Sep 17 00:00:00 2001 From: jens Date: Tue, 7 Jul 2026 19:07:59 +0200 Subject: [PATCH 2/2] Move Paper-specific entity trait calls behind NMS bridge --- .../trait/versioned/CopperGolemTrait.java | 4 ++-- .../citizensnpcs/trait/versioned/MannequinTrait.java | 4 ++-- main/src/main/java/net/citizensnpcs/util/NMS.java | 8 ++++++++ .../main/java/net/citizensnpcs/util/NMSBridge.java | 6 ++++++ .../net/citizensnpcs/nms/v1_21_R7/util/NMSImpl.java | 12 +++++++++++- .../net/citizensnpcs/nms/v26_1_R1/util/NMSImpl.java | 12 +++++++++++- .../net/citizensnpcs/nms/v26_2_R1/util/NMSImpl.java | 12 +++++++++++- 7 files changed, 51 insertions(+), 7 deletions(-) diff --git a/main/src/main/java/net/citizensnpcs/trait/versioned/CopperGolemTrait.java b/main/src/main/java/net/citizensnpcs/trait/versioned/CopperGolemTrait.java index ea1bddf43..6164dc62f 100644 --- a/main/src/main/java/net/citizensnpcs/trait/versioned/CopperGolemTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/versioned/CopperGolemTrait.java @@ -86,7 +86,7 @@ public static void copperGolem(CommandContext args, CommandSender sender, NPC np output += Messaging.tr(Messages.COPPER_WEATHER_STATE_SET, state); } if (tick != null) { - ((CopperGolem) npc.getEntity()).setNextWeatheringTick(tick); + NMS.setCopperGolemWeatheringTick(npc.getEntity(), tick); output += Messaging.tr(Messages.COPPER_WEATHER_TICK_SET, tick); } if (!output.isEmpty()) { @@ -112,4 +112,4 @@ public static void copperGolem(CommandContext args, CommandSender sender, NPC np } } } -} \ No newline at end of file +} diff --git a/main/src/main/java/net/citizensnpcs/trait/versioned/MannequinTrait.java b/main/src/main/java/net/citizensnpcs/trait/versioned/MannequinTrait.java index 7a4c4136b..a835aae1e 100644 --- a/main/src/main/java/net/citizensnpcs/trait/versioned/MannequinTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/versioned/MannequinTrait.java @@ -48,7 +48,7 @@ public void run() { description == null ? null : Messaging.minecraftComponentFromRawMessage(description)); } mannequin.setImmovable(immovable); - mannequin.setHideDescription(hideDescription); + NMS.setMannequinHideDescription(mannequin, hideDescription); } } @@ -105,4 +105,4 @@ public static void mannequin(CommandContext args, CommandSender sender, NPC npc, Messaging.send(sender, output); } } -} \ No newline at end of file +} diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index ef116b04d..58ba96341 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -951,6 +951,10 @@ public static void setHeadYaw(Entity entity, float yaw) { BRIDGE.setHeadYaw(entity, yaw); } + public static void setCopperGolemWeatheringTick(Entity copperGolem, long tick) { + BRIDGE.setCopperGolemWeatheringTick(copperGolem, tick); + } + public static void setKnockbackResistance(org.bukkit.entity.LivingEntity entity, double d) { BRIDGE.setKnockbackResistance(entity, d); } @@ -967,6 +971,10 @@ public static void setMannequinDescription(Entity mannequin, Object component) { BRIDGE.setMannequinDescription(mannequin, component); } + public static void setMannequinHideDescription(Entity mannequin, boolean hide) { + BRIDGE.setMannequinHideDescription(mannequin, hide); + } + public static void setNavigationTarget(Entity handle, Entity target, float speed) { BRIDGE.setNavigationTarget(handle, target, speed); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index af410f87d..a2454686e 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -237,6 +237,9 @@ public default void setCamelPose(Entity entity, CamelPose pose) { public void setHeadYaw(Entity entity, float yaw); + public default void setCopperGolemWeatheringTick(Entity copperGolem, long tick) { + } + public default void setKnockbackResistance(LivingEntity entity, double d) { AttributeInstance ai = entity.getAttribute(Attribute.KNOCKBACK_RESISTANCE); if (ai != null) { @@ -253,6 +256,9 @@ public default void setLyingDown(Entity cat, boolean lying) { public default void setMannequinDescription(Entity mannequin, Object component) { } + public default void setMannequinHideDescription(Entity mannequin, boolean hide) { + } + public void setNavigationTarget(Entity handle, Entity target, float speed); public void setNavigationType(Entity entity, MinecraftNavigationType type); diff --git a/v1_21_R7/src/main/java/net/citizensnpcs/nms/v1_21_R7/util/NMSImpl.java b/v1_21_R7/src/main/java/net/citizensnpcs/nms/v1_21_R7/util/NMSImpl.java index ac7bb00dc..2a016178b 100644 --- a/v1_21_R7/src/main/java/net/citizensnpcs/nms/v1_21_R7/util/NMSImpl.java +++ b/v1_21_R7/src/main/java/net/citizensnpcs/nms/v1_21_R7/util/NMSImpl.java @@ -1678,6 +1678,16 @@ public void setMannequinDescription(org.bukkit.entity.Entity mannequin, Object c ((Mannequin) getHandle(mannequin)).setDescription((Component) component); } + @Override + public void setMannequinHideDescription(org.bukkit.entity.Entity mannequin, boolean hide) { + ((Mannequin) getHandle(mannequin)).setHideDescription(hide); + } + + @Override + public void setCopperGolemWeatheringTick(org.bukkit.entity.Entity copperGolem, long tick) { + ((net.minecraft.world.entity.animal.golem.CopperGolem) getHandle(copperGolem)).nextWeatheringTick = tick; + } + @Override public void setNavigationTarget(org.bukkit.entity.Entity handle, org.bukkit.entity.Entity target, float speed) { getNavigation(handle).moveTo(getHandle(target), speed); @@ -2912,4 +2922,4 @@ public static void updateMinecraftAIState(NPC npc, Mob entity) { Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); } } -} \ No newline at end of file +} diff --git a/v26_1_R1/src/main/java/net/citizensnpcs/nms/v26_1_R1/util/NMSImpl.java b/v26_1_R1/src/main/java/net/citizensnpcs/nms/v26_1_R1/util/NMSImpl.java index 22b4e7798..2e67be1fb 100644 --- a/v26_1_R1/src/main/java/net/citizensnpcs/nms/v26_1_R1/util/NMSImpl.java +++ b/v26_1_R1/src/main/java/net/citizensnpcs/nms/v26_1_R1/util/NMSImpl.java @@ -1681,6 +1681,16 @@ public void setMannequinDescription(org.bukkit.entity.Entity mannequin, Object c ((Mannequin) getHandle(mannequin)).setDescription((Component) component); } + @Override + public void setMannequinHideDescription(org.bukkit.entity.Entity mannequin, boolean hide) { + ((Mannequin) getHandle(mannequin)).setHideDescription(hide); + } + + @Override + public void setCopperGolemWeatheringTick(org.bukkit.entity.Entity copperGolem, long tick) { + ((net.minecraft.world.entity.animal.golem.CopperGolem) getHandle(copperGolem)).nextWeatheringTick = tick; + } + @Override public void setNavigationTarget(org.bukkit.entity.Entity handle, org.bukkit.entity.Entity target, float speed) { getNavigation(handle).moveTo(getHandle(target), speed); @@ -3059,4 +3069,4 @@ public void acceptEmpty(MemoryModuleType type) { Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); } } -} \ No newline at end of file +} diff --git a/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/util/NMSImpl.java b/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/util/NMSImpl.java index 9f9234bdb..741b10098 100644 --- a/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/util/NMSImpl.java +++ b/v26_2_R1/src/main/java/net/citizensnpcs/nms/v26_2_R1/util/NMSImpl.java @@ -1684,6 +1684,16 @@ public void setMannequinDescription(org.bukkit.entity.Entity mannequin, Object c ((Mannequin) getHandle(mannequin)).setDescription((Component) component); } + @Override + public void setMannequinHideDescription(org.bukkit.entity.Entity mannequin, boolean hide) { + ((Mannequin) getHandle(mannequin)).setHideDescription(hide); + } + + @Override + public void setCopperGolemWeatheringTick(org.bukkit.entity.Entity copperGolem, long tick) { + ((net.minecraft.world.entity.animal.golem.CopperGolem) getHandle(copperGolem)).nextWeatheringTick = tick; + } + @Override public void setNavigationTarget(org.bukkit.entity.Entity handle, org.bukkit.entity.Entity target, float speed) { getNavigation(handle).moveTo(getHandle(target), speed); @@ -3091,4 +3101,4 @@ public void acceptEmpty(MemoryModuleType type) { Messaging.logTr(Messages.ERROR_GETTING_ID_MAPPING, e.getMessage()); } } -} \ No newline at end of file +}