From dedbe94cd8e2a9551ee808d7a2b24c678c0819ce Mon Sep 17 00:00:00 2001 From: KAMKEEL <28842281+KAMKEEL@users.noreply.github.com> Date: Tue, 11 Aug 2026 04:44:14 -0400 Subject: [PATCH] Keep client-only sub-GUI types out of Ability's method descriptors The magic editor field was built with lambdas inside Ability.getAllDefinitions. subGuiField is generic, so those lambdas took SubGuiAbilityMagic as their descriptor type. @SideOnly strips the annotated method on a server but not the synthetic lambdas it generates, so anything reflecting over Ability's declared methods - Nashorn's adapter generator when a script touches an ability - hit NoClassDefFoundError. Building the field in the client class keeps the type out of Ability entirely. --- .../controllers/data/ability/Ability.java | 14 +--------- .../gui/advanced/SubGuiAbilityMagic.java | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java b/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java index 05049d8bb..a73a8a0a2 100644 --- a/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java +++ b/src/main/java/kamkeel/npcs/controllers/data/ability/Ability.java @@ -840,19 +840,7 @@ public abstract class Ability implements IAbility, IAbilityAction { return sb.toString(); }).tab("General")); - defs.add(FieldDef.subGuiField("ability.magic.editor", - () -> new SubGuiAbilityMagic(magicData.copy()), - gui -> { - MagicData result = ((SubGuiAbilityMagic) gui).magicData; - magicData.getMagics().clear(); - for (Map.Entry e : result.getMagics().entrySet()) { - magicData.getMagics().put(e.getKey(), e.getValue()); - } - }) - .buttonLabel(() -> magicData.isEmpty() - ? StatCollector.translateToLocal("ability.magic.usesCaster") - : magicData.getMagics().size() + " Magic(s)") - .tab("General")); + defs.add(SubGuiAbilityMagic.createMagicField(magicData)); } // ── Target tab ─────────────────────────────────────────────── diff --git a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityMagic.java b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityMagic.java index 8543ad208..8f555017a 100644 --- a/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityMagic.java +++ b/src/main/java/noppes/npcs/client/gui/advanced/SubGuiAbilityMagic.java @@ -1,6 +1,8 @@ package noppes.npcs.client.gui.advanced; import net.minecraft.client.gui.GuiButton; +import net.minecraft.util.StatCollector; +import noppes.npcs.client.gui.builder.FieldDef; import noppes.npcs.client.gui.util.GuiCustomScroll; import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; @@ -11,6 +13,7 @@ import noppes.npcs.client.gui.util.SubGuiInterface; import noppes.npcs.controllers.MagicController; import noppes.npcs.controllers.data.Magic; import noppes.npcs.controllers.data.MagicData; +import noppes.npcs.controllers.data.MagicEntry; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -36,6 +39,30 @@ public class SubGuiAbilityMagic extends SubGuiInterface implements ICustomScroll private GuiNpcTextField splitField; + /** + * Builds the ability editor's magic field. + *

+ * This lives here rather than in Ability because the lambdas below carry this class in + * their method descriptors. Ability is a both-side class, and anything reflecting over its + * declared methods on a server - Nashorn's adapter generator, for one - would resolve those + * descriptors and fail to find this client-only type. + */ + public static FieldDef createMagicField(MagicData magicData) { + return FieldDef.subGuiField("ability.magic.editor", + () -> new SubGuiAbilityMagic(magicData.copy()), + gui -> { + MagicData result = ((SubGuiAbilityMagic) gui).magicData; + magicData.getMagics().clear(); + for (Map.Entry e : result.getMagics().entrySet()) { + magicData.getMagics().put(e.getKey(), e.getValue()); + } + }) + .buttonLabel(() -> magicData.isEmpty() + ? StatCollector.translateToLocal("ability.magic.usesCaster") + : magicData.getMagics().size() + " Magic(s)") + .tab("General"); + } + public SubGuiAbilityMagic(MagicData data) { this.magicData = data; setBackground("menubg.png");