From ca8285e23f960297cc4477d42153302de52ed0be Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Mon, 12 Jan 2026 03:28:18 +0200 Subject: [PATCH 01/19] Made these 3 detached GuiScripts depend on GuiScriptInterface --- .../client/gui/script/GuiScriptEffect.java | 415 +---------------- .../client/gui/script/GuiScriptInterface.java | 189 +++++++- .../gui/script/GuiScriptLinkedItem.java | 416 +---------------- .../client/gui/script/GuiScriptRecipe.java | 423 +----------------- 4 files changed, 234 insertions(+), 1209 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java index 796b81058..1f51339f1 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java @@ -1,423 +1,52 @@ package noppes.npcs.client.gui.script; import kamkeel.npcs.network.packets.request.script.EffectScriptPacket; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiConfirmOpenLink; -import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.StatCollector; -import noppes.npcs.NBTTags; -import noppes.npcs.NoppesStringUtils; import noppes.npcs.client.gui.global.GuiNPCManageEffects; -import noppes.npcs.client.gui.util.GuiCustomScroll; -import noppes.npcs.client.gui.util.GuiMenuTopButton; -import noppes.npcs.client.gui.util.GuiNPCInterface; -import noppes.npcs.client.gui.util.GuiNpcButton; -import noppes.npcs.client.gui.util.GuiNpcLabel; -import noppes.npcs.client.gui.util.GuiNpcTextArea; -import noppes.npcs.client.gui.util.GuiNpcTextField; -import noppes.npcs.client.gui.util.GuiScriptTextArea; -import noppes.npcs.client.gui.util.ICustomScrollListener; -import noppes.npcs.client.gui.util.IGuiData; -import noppes.npcs.client.gui.util.IJTextAreaListener; -import noppes.npcs.client.gui.util.ITextChangeListener; -import noppes.npcs.client.gui.util.ITextfieldListener; -import noppes.npcs.api.handler.IScriptHookHandler; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.CustomEffect; import noppes.npcs.controllers.data.EffectScript; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +public class GuiScriptEffect extends GuiScriptInterface { -public class GuiScriptEffect extends GuiNPCInterface implements GuiYesNoCallback, IGuiData, ITextChangeListener, ICustomScrollListener, IJTextAreaListener, ITextfieldListener { - - private int activeTab = 0; - public Map> languages = new HashMap(); - private final int scriptLimit = 1; - public List hookList = new ArrayList(); - public String previousHookClicked = ""; - - public final GuiNPCManageEffects parent; public final CustomEffect effect; private final EffectScript scriptHandler; - boolean loaded = false; - - private GuiScriptTextArea textArea; - public GuiScriptEffect(GuiNPCManageEffects parent, CustomEffect effect) { - this.drawDefaultBackground = true; - this.closeOnEsc = true; - this.xSize = 420; - this.setBackground("menubg.png"); - + super(); this.parent = parent; this.effect = effect; this.scriptHandler = new EffectScript(); + this.handler = this.scriptHandler; + this.singleContainer = true; this.hookList = new ArrayList<>(ScriptHookController.Instance.getAllHooks(IScriptHookHandler.CONTEXT_EFFECT)); EffectScriptPacket.Get(effect.id); } - public void initGui() { - this.ySize = (int) ((double) this.xSize * 0.56); - if ((double) this.ySize > (double) this.height * 0.95) { - this.ySize = (int) ((double) this.height * 0.95); - this.xSize = (int) ((double) this.ySize / 0.56); - } - - this.bgScale = (float) this.xSize / 400.0F; - super.initGui(); - this.guiTop += 10; - int yoffset = (int) ((double) this.ySize * 0.02); - GuiMenuTopButton top; - this.addTopButton(top = new GuiMenuTopButton(0, this.guiLeft + 4, this.guiTop - 17, "gui.settings")); - int topXoffset = 0; - int topYoffset = 0; - - - if (this.scriptHandler.container != null) { - this.addTopButton(top = new GuiMenuTopButton(1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, "Script")); - - } else { - this.addTopButton(new GuiMenuTopButton(this.scriptLimit, top.xPosition + top.width, top.yPosition, "+")); - } - - top = this.getTopButton(this.activeTab); - if (top == null) { - this.activeTab = 0; - top = this.getTopButton(0); - } - - top.active = true; - if (this.activeTab == 1) { - GuiCustomScroll hooks = new GuiCustomScroll(this, 1); - hooks.allowUserInput = false; - hooks.setSize(108, 198); - hooks.guiLeft = this.guiLeft - 110; - hooks.guiTop = this.guiTop + 14; - - hooks.setUnsortedList(this.hookList); - this.addScroll(hooks); - GuiNpcLabel hookLabel = new GuiNpcLabel(0, "script.hooks", hooks.guiLeft, this.guiTop + 5); - hookLabel.color = 11184810; - this.addLabel(hookLabel); - ScriptContainer container = this.scriptHandler.container; - if (textArea == null) - textArea = new GuiScriptTextArea(this, 2, this.guiLeft + 1 + yoffset, this.guiTop + yoffset, this.xSize - 108 - yoffset, (int) ((double) this.ySize * 0.96) - yoffset * 2, container == null ? "" : container.script); - else - textArea.init(this.guiLeft + 1 + yoffset, this.guiTop + yoffset, this.xSize - 108 - yoffset, (int) ((double) this.ySize * 0.96) - yoffset * 2, container == null ? "" : container.script); - textArea.enableCodeHighlighting(); - textArea.setListener(this); - this.closeOnEsc(textArea::closeOnEsc); - this.addTextField(textArea); - - int left1 = this.guiLeft + this.xSize - 104; - this.addButton(new GuiNpcButton(102, left1, this.guiTop + yoffset, 60, 20, "gui.clear")); - this.addButton(new GuiNpcButton(101, left1 + 61, this.guiTop + yoffset, 60, 20, "gui.paste")); - this.addButton(new GuiNpcButton(100, left1, this.guiTop + 21 + yoffset, 60, 20, "gui.copy")); - this.addButton(new GuiNpcButton(105, left1 + 61, this.guiTop + 21 + yoffset, 60, 20, "gui.remove")); - - this.addButton(new GuiNpcButton(107, left1, this.guiTop + 66 + yoffset, 80, 20, "script.loadscript")); - this.getButton(107).enabled = false; - - GuiCustomScroll scroll = (new GuiCustomScroll(this, 0)).setUnselectable(); - scroll.setSize(100, (int) ((double) this.ySize * 0.54) - yoffset * 2); - scroll.guiLeft = left1; - scroll.guiTop = this.guiTop + 88 + yoffset; - if (container != null) { - scroll.setList(container.scripts); - } - - this.addScroll(scroll); - } else { - GuiNpcTextArea var8 = new GuiNpcTextArea(2, this, this.guiLeft + 4 + yoffset, this.guiTop + 6 + yoffset, this.xSize - 160 - yoffset, (int) ((float) this.ySize * 0.92F) - yoffset * 2, this.getConsoleText()); - var8.enabled = false; - this.addTextField(var8); - int var9 = this.guiLeft + this.xSize - 150; - this.addButton(new GuiNpcButton(100, var9, this.guiTop + 125, 60, 20, "gui.copy")); - this.addButton(new GuiNpcButton(102, var9, this.guiTop + 146, 60, 20, "gui.clear")); - this.addLabel(new GuiNpcLabel(1, "script.language", var9, this.guiTop + 15)); - this.addButton(new GuiNpcButton(103, var9 + 60, this.guiTop + 10, 80, 20, this.languages.keySet().toArray(new String[this.languages.keySet().size()]), this.getScriptIndex())); - this.getButton(103).enabled = !this.languages.isEmpty(); - this.addLabel(new GuiNpcLabel(2, "gui.enabled", var9, this.guiTop + 36)); - this.addButton(new GuiNpcButton(104, var9 + 60, this.guiTop + 31, 50, 20, new String[]{"gui.no", "gui.yes"}, this.scriptHandler.getEnabled() ? 1 : 0)); - - this.addButton(new GuiNpcButton(109, var9, this.guiTop + 78, 80, 20, "gui.website")); - this.addButton(new GuiNpcButton(112, var9 + 81, this.guiTop + 78, 80, 20, "gui.forum")); - this.addButton(new GuiNpcButton(110, var9, this.guiTop + 99, 80, 20, "script.apidoc")); - this.addButton(new GuiNpcButton(111, var9 + 81, this.guiTop + 99, 80, 20, "script.apisrc")); - } - - this.xSize = 420; - this.ySize = 256; + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.GLOBAL; } - public void customScrollClicked(int i, int j, int k, GuiCustomScroll scroll) { - String hook = scroll.getSelected(); - if (this.previousHookClicked.equals(hook)) { - String addString = ""; - if (!this.getTextField(2).getText().isEmpty()) { - addString = addString + "\n"; - } - - addString = addString + "function " + hook + "(event) {\n \n}\n"; - this.getTextField(2).setText(this.getTextField(2).getText() + addString); - this.previousHookClicked = ""; - } else { - this.previousHookClicked = hook; - } - - } - - public void unFocused(GuiNpcTextField textfield) { - } - - private String getConsoleText() { - Map map = this.scriptHandler.getConsoleText(); - StringBuilder builder = new StringBuilder(); - Iterator var3 = map.entrySet().iterator(); - - while (var3.hasNext()) { - Map.Entry entry = (Map.Entry) var3.next(); - builder.insert(0, new Date((Long) entry.getKey()) + (String) entry.getValue() + "\n"); - } - - return builder.toString(); - } - - private int getScriptIndex() { - int i = 0; - - for (Iterator var2 = this.languages.keySet().iterator(); var2.hasNext(); ++i) { - String language = (String) var2.next(); - if (language.equalsIgnoreCase(this.scriptHandler.getLanguage())) { - return i; - } - } - - return 0; - } - - public void confirmClicked(boolean flag, int i) { - if (flag) { - if (i == 0) { - this.openLink("https://www.curseforge.com/minecraft/mc-mods/customnpc-plus"); - } - - if (i == 1) { - this.openLink("https://kamkeel.github.io/CustomNPC-Plus/"); - } - - if (i == 2) { - this.openLink("https://kamkeel.github.io/CustomNPC-Plus/"); - } - - if (i == 3) { - this.openLink("http://www.minecraftforge.net/forum/index.php/board,122.0.html"); - } - - if (i == 10) { - this.scriptHandler.container = null; - this.activeTab = 0; - } - - if (i == 101) { - this.getTextField(2).setText(NoppesStringUtils.getClipboardContents()); - this.setScript(); - } - - if (i == 102) { - if (this.activeTab == 1) { - ScriptContainer container = this.scriptHandler.container; - container.script = ""; - } else { - this.scriptHandler.clearConsole(); - } - - this.initGui(); - } - } - - this.displayGuiScreen(this); - } - - protected void actionPerformed(GuiButton guibutton) { - if (guibutton.id == 0) { - this.setScript(); - this.activeTab = 0; - this.initGui(); - } - - if (guibutton.id == this.scriptLimit) { - if (scriptHandler.container == null) - this.scriptHandler.container = new ScriptContainer(this.scriptHandler); - else - this.setScript(); - this.activeTab = 1; - this.initGui(); - } - - if (guibutton.id == 109) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://kamkeel.github.io/CustomNPC-Plus/", 0, true)); - } - - if (guibutton.id == 110) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://github.com/KAMKEEL/CustomNPC-Plus-API", 1, true)); - } - - if (guibutton.id == 111) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://github.com/Noppes/CustomNPCsAPI", 2, true)); - } - - if (guibutton.id == 112) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "http://www.minecraftforge.net/forum/index.php/board,122.0.html", 3, true)); - } - - if (guibutton.id == 100) { - NoppesStringUtils.setClipboardContents(this.getTextField(2).getText()); - } - - if (guibutton.id == 101) { - GuiYesNo guiyesno = new GuiYesNo(this, StatCollector.translateToLocal("gui.paste"), StatCollector.translateToLocal("gui.sure"), 101); - this.displayGuiScreen(guiyesno); - } - - GuiYesNo container1; - if (guibutton.id == 102) { - container1 = new GuiYesNo(this, StatCollector.translateToLocal("gui.clear"), StatCollector.translateToLocal("gui.sure"), 102); - this.displayGuiScreen(container1); - } - - if (guibutton.id == 103) { - this.scriptHandler.setLanguage(guibutton.displayString); - } - - if (guibutton.id == 104) { - this.scriptHandler.setEnabled(((GuiNpcButton) guibutton).getValue() == 1); - } - - if (guibutton.id == 105) { - container1 = new GuiYesNo(this, "", ((GuiNpcButton) guibutton).displayString, 10); - this.displayGuiScreen(container1); - } - - if (guibutton.id == 107) { - ScriptContainer container = this.scriptHandler.container; - if (container == null) { - container = new ScriptContainer(this.scriptHandler); - this.scriptHandler.container = container; - } - -// this.setSubGui(new EventGuiScriptList((List)this.languages.get(this.script.getLanguage()), container)); - } - - } - - private void setScript() { - if (this.activeTab == 1) { - ScriptContainer container = this.scriptHandler.container; - if (container == null) { - container = new ScriptContainer(this.scriptHandler); - this.scriptHandler.container = container; - } - - String text = this.getTextField(2).getText(); - text = text.replace("\r\n", "\n"); - text = text.replace("\r", "\n"); - container.script = text; - } - - } - - public void setGuiData(NBTTagCompound compound) { - if (compound.hasKey("LoadComplete")) { - loaded = true; - return; - } - - if (!compound.hasKey("Tab")) { - this.scriptHandler.setLanguage(compound.getString("ScriptLanguage")); - this.scriptHandler.setEnabled(compound.getBoolean("ScriptEnabled")); - this.copiedSetGuiData(compound); - } else { - int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(this.scriptHandler); - container.readFromNBT(compound.getCompoundTag("Script")); - this.scriptHandler.container = container; - this.initGui(); - } - } - - private void copiedSetGuiData(NBTTagCompound compound) { - NBTTagList data = compound.getTagList("Languages", 10); - HashMap languages = new HashMap(); - - for (int i = 0; i < data.tagCount(); ++i) { - NBTTagCompound comp = data.getCompoundTagAt(i); - ArrayList scripts = new ArrayList(); - NBTTagList list = comp.getTagList("Scripts", 8); - - for (int j = 0; j < list.tagCount(); ++j) { - scripts.add(list.getStringTagAt(j)); - } - - languages.put(comp.getString("Language"), scripts); - } - - this.languages = languages; - this.initGui(); - } - - public void save() { - if (loaded) { - this.setScript(); - - List containers = this.scriptHandler.getScripts(); - for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); - EffectScriptPacket.Save(effect.id, i, containers.size(), container.writeToNBT(new NBTTagCompound())); - } - NBTTagCompound scriptData = new NBTTagCompound(); - scriptData.setString("ScriptLanguage", this.scriptHandler.getLanguage()); - scriptData.setBoolean("ScriptEnabled", this.scriptHandler.getEnabled()); - scriptData.setTag("ScriptConsole", NBTTags.NBTLongStringMap(this.scriptHandler.getConsoleText())); - - EffectScriptPacket.Save(effect.id, -1, containers.size(), scriptData); - } - } - - public void textUpdate(String text) { - ScriptContainer container = this.scriptHandler.container; - if (container != null) { - container.script = text; - } - - } - - public void saveText(String text) { - ScriptContainer container = this.scriptHandler.container; - if (container != null) { - container.script = text; - } - - this.initGui(); + protected void setHandlerContainer(ScriptContainer container) { + this.scriptHandler.container = container; } @Override - public void close() { - this.save(); - parent.setWorldAndResolution(mc, width, height); - parent.initGui(); - mc.currentScreen = parent; + public void setGuiData(NBTTagCompound compound) { + setGuiDataWithOldContainer(compound); } -} + + protected void sendSavePacket(int index, int totalCount, NBTTagCompound scriptNBT) { + EffectScriptPacket.Save(effect.id, index, totalCount, scriptNBT); + } + + @Override + public void save() { + saveWithPackets(); + } +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 1a00de918..765f29f60 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -1,9 +1,6 @@ package noppes.npcs.client.gui.script; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiConfirmOpenLink; -import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; +import net.minecraft.client.gui.*; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ResourceLocation; @@ -49,6 +46,9 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb protected boolean loaded = false; private Map textAreas = new HashMap<>(); + protected GuiScreen parent; + + public boolean singleContainer = false; // ==================== FULLSCREEN MODE ==================== /** Whether the editor viewport is currently in fullscreen mode */ @@ -101,20 +101,28 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb int topXoffset = 0; int topYoffset = 0; - for (int ta = 0; ta < this.handler.getScripts().size(); ++ta) { - if (ta % 20 == 0 && ta > 0) { - topYoffset -= 20; - topXoffset -= top.width + 20 * 22; + if(!singleContainer) { + for (int ta = 0; ta < this.handler.getScripts().size(); ++ta) { + if (ta % 20 == 0 && ta > 0) { + topYoffset -= 20; + topXoffset -= top.width + 20 * 22; + } + this.addTopButton(top = new GuiMenuTopButton(ta + 1, top.xPosition + top.width + topXoffset, + top.yPosition + topYoffset, ta + 1 + "")); + topXoffset = 0; + topYoffset = 0; + scriptLimit = ta + 2; } - this.addTopButton(top = new GuiMenuTopButton(ta + 1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, ta + 1 + "")); - topXoffset = 0; - topYoffset = 0; - scriptLimit = ta + 2; } - if (this.handler.getScripts().size() < 100) + if (singleContainer && getFirst() != null) + this.addTopButton( + top = new GuiMenuTopButton(1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, + "Script")); + else if (this.handler.getScripts().size() < 100) this.addTopButton(new GuiMenuTopButton(scriptLimit, top.xPosition + top.width, top.yPosition, "+")); + top = this.getTopButton(this.activeTab); if (top == null) { this.activeTab = 0; @@ -322,7 +330,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb return builder.toString(); } - private int getScriptIndex() { + public int getScriptIndex() { int i = 0; for (Iterator var2 = this.languages.keySet().iterator(); var2.hasNext(); ++i) { @@ -353,7 +361,10 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb this.openLink("http://www.minecraftforge.net/forum/index.php/board,122.0.html"); } if (i == 10) { - this.handler.getScripts().remove(this.activeTab - 1); + if (singleContainer) + setHandlerContainer(null); + else + this.handler.getScripts().remove(this.activeTab - 1); this.activeTab = 0; } if (i == 101) { @@ -378,7 +389,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb this.displayGuiScreen(this); } - private GuiScriptTextArea getActiveScriptArea() { + public GuiScriptTextArea getActiveScriptArea() { if (this.activeTab > 0) { int idx = this.activeTab - 1; if (idx >= 0 && idx < textAreas.size()) @@ -397,6 +408,11 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb return super.getTextField(id); } + public ScriptContainer getFirst() { + if (this.handler.getScripts().isEmpty()) + return null; + return this.handler.getScripts().get(0); + } @Override protected void actionPerformed(GuiButton guibutton) { if (guibutton.id >= 0 && guibutton.id < scriptLimit) { @@ -406,8 +422,16 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } if (guibutton.id == scriptLimit) { - this.handler.getScripts().add(new ScriptContainer(this.handler)); - this.activeTab = this.handler.getScripts().size(); + if (singleContainer) { + if (getFirst() == null) + setHandlerContainer(new ScriptContainer(handler)); + else + this.setScript(); + this.activeTab = 1; + } else { + this.handler.getScripts().add(new ScriptContainer(this.handler)); + this.activeTab = this.handler.getScripts().size(); + } this.initGui(); } @@ -464,18 +488,26 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb if (guibutton.id == 107) { container = (ScriptContainer) this.handler.getScripts().get(this.activeTab - 1); if (container == null) { - this.handler.getScripts().add(container = new ScriptContainer(this.handler)); + container = new ScriptContainer(this.handler); + if (singleContainer) + setHandlerContainer(container); + else + this.handler.getScripts().add(container); } this.setSubGui(new EventGuiScriptList((List) this.languages.get(this.handler.getLanguage()), container)); } } - private void setScript() { + protected void setScript() { if (this.activeTab > 0) { ScriptContainer container = (ScriptContainer) this.handler.getScripts().get(this.activeTab - 1); if (container == null) { - this.handler.getScripts().add(container = new ScriptContainer(this.handler)); + container = new ScriptContainer(this.handler); + if (singleContainer) + setHandlerContainer(container); + else + this.handler.getScripts().add(container); } String text = (this.getTextField(2)).getText(); @@ -506,6 +538,106 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb this.initGui(); } + /** + * Get the script context for this GUI. + * Override in subclasses to return the appropriate context. + * + * @return The script context (default: GLOBAL) + */ + protected ScriptContext getScriptContext() { + return ScriptContext.GLOBAL; + } + + // ==================== UNIFIED SCRIPT DATA HANDLING ==================== + + /** + * Unified setGuiData for script GUIs with old container system. + * Handles both language data and tab-specific script loading. + */ + protected void setGuiDataWithOldContainer(NBTTagCompound compound) { + if (compound.hasKey("LoadComplete")) { + loaded = true; + return; + } + + if (!compound.hasKey("Tab")) { + this.handler.setLanguage(compound.getString("ScriptLanguage")); + this.handler.setEnabled(compound.getBoolean("ScriptEnabled")); + this.loadLanguagesData(compound); + } else { + int tab = compound.getInteger("Tab"); + ScriptContainer container = new ScriptContainer(this.handler); + container.readFromNBT(compound.getCompoundTag("Script")); + this.setHandlerContainer(container); + this.initGui(); + } + } + + /** + * Load languages data from NBT. + * Separated for potential override in subclasses if needed. + */ + protected void loadLanguagesData(NBTTagCompound compound) { + NBTTagList data = compound.getTagList("Languages", 10); + HashMap languages = new HashMap(); + + for (int i = 0; i < data.tagCount(); ++i) { + NBTTagCompound comp = data.getCompoundTagAt(i); + java.util.ArrayList scripts = new java.util.ArrayList(); + NBTTagList list = comp.getTagList("Scripts", 8); + + for (int j = 0; j < list.tagCount(); ++j) { + scripts.add(list.getStringTagAt(j)); + } + + languages.put(comp.getString("Language"), scripts); + } + + this.languages = languages; + this.initGui(); + } + + /** + * Set the handler's container. Override if handler is not IScriptHandler. + */ + protected void setHandlerContainer(ScriptContainer container) { + // Default implementation - subclasses may need to cast and set differently + // e.g., ((LinkedItemScript) handler).container = container; + } + + /** + * Unified save method for script GUIs with packet-based saving. + * Subclasses only need to override sendScriptPackets() and sendMetadataPacket(). + */ + protected void saveWithPackets() { + if (loaded) { + this.setScript(); + + List containers = this.handler.getScripts(); + for (int i = 0; i < containers.size(); i++) { + ScriptContainer container = containers.get(i); + sendSavePacket(i, containers.size(), container.writeToNBT(new NBTTagCompound())); + } + + NBTTagCompound scriptData = new NBTTagCompound(); + scriptData.setString("ScriptLanguage", this.handler.getLanguage()); + scriptData.setBoolean("ScriptEnabled", this.handler.getEnabled()); + scriptData.setTag("ScriptConsole", noppes.npcs.NBTTags.NBTLongStringMap(this.handler.getConsoleText())); + + sendSavePacket(-1, containers.size(), scriptData); + } + } + + /** + * Send a script container packet. Override in subclasses. + * @param index The index of this script + * @param totalCount Total number of scripts + * @param scriptNBT The script container NBT data + */ + protected void sendSavePacket(int index, int totalCount, NBTTagCompound scriptNBT) { + // Default: do nothing (for non-packet-based GUIs like GuiScriptItem) + } + public void save() { if (loaded) this.setScript(); @@ -519,14 +651,27 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } + @Deprecated @Override + //NEVER USED public void saveText(String text) { - ScriptContainer container = handler.getScripts().get(activeTab); + ScriptContainer container = handler.getScripts().get(activeTab ); //activeTab - 1? if (container != null) container.script = text; initGui(); } + @Override + public void close() { + if (parent != null) { + this.save(); + parent.setWorldAndResolution(mc, width, height); + parent.initGui(); + mc.currentScreen = parent; + } else + super.close(); + } + // ==================== FULLSCREEN METHODS ==================== /** diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java index 9091a6ceb..306b62a91 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java @@ -1,423 +1,51 @@ package noppes.npcs.client.gui.script; import kamkeel.npcs.network.packets.request.script.item.LinkedItemScriptPacket; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiConfirmOpenLink; -import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.StatCollector; -import noppes.npcs.NBTTags; -import noppes.npcs.NoppesStringUtils; import noppes.npcs.client.gui.global.GuiNPCManageLinked; -import noppes.npcs.client.gui.util.GuiCustomScroll; -import noppes.npcs.client.gui.util.GuiMenuTopButton; -import noppes.npcs.client.gui.util.GuiNPCInterface; -import noppes.npcs.client.gui.util.GuiNpcButton; -import noppes.npcs.client.gui.util.GuiNpcLabel; -import noppes.npcs.client.gui.util.GuiNpcTextArea; -import noppes.npcs.client.gui.util.GuiNpcTextField; -import noppes.npcs.client.gui.util.GuiScriptTextArea; -import noppes.npcs.client.gui.util.ICustomScrollListener; -import noppes.npcs.client.gui.util.IGuiData; -import noppes.npcs.client.gui.util.IJTextAreaListener; -import noppes.npcs.client.gui.util.ITextChangeListener; -import noppes.npcs.client.gui.util.ITextfieldListener; -import noppes.npcs.api.handler.IScriptHookHandler; +import noppes.npcs.constants.EnumScriptType; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.LinkedItem; import noppes.npcs.controllers.data.LinkedItemScript; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +public class GuiScriptLinkedItem extends GuiScriptInterface { -public class GuiScriptLinkedItem extends GuiNPCInterface implements GuiYesNoCallback, IGuiData, ITextChangeListener, ICustomScrollListener, IJTextAreaListener, ITextfieldListener { - - private int activeTab = 0; - public Map> languages = new HashMap(); - private final int scriptLimit = 1; - public List hookList = new ArrayList(); - public String previousHookClicked = ""; - - public final GuiNPCManageLinked parent; public final LinkedItem linkedItem; - private final LinkedItemScript scriptHandler; - boolean loaded = false; - - private GuiScriptTextArea textArea; public GuiScriptLinkedItem(GuiNPCManageLinked parent, LinkedItem linkedItem) { - this.drawDefaultBackground = true; - this.closeOnEsc = true; - this.xSize = 420; - this.setBackground("menubg.png"); - + super(); this.parent = parent; this.linkedItem = linkedItem; - this.scriptHandler = new LinkedItemScript(); + this.handler = new LinkedItemScript(); + this.singleContainer = true; this.hookList = new ArrayList<>(ScriptHookController.Instance.getAllHooks(IScriptHookHandler.CONTEXT_LINKED_ITEM)); LinkedItemScriptPacket.Get(linkedItem.id); } - public void initGui() { - this.ySize = (int) ((double) this.xSize * 0.56); - if ((double) this.ySize > (double) this.height * 0.95) { - this.ySize = (int) ((double) this.height * 0.95); - this.xSize = (int) ((double) this.ySize / 0.56); - } - - this.bgScale = (float) this.xSize / 400.0F; - super.initGui(); - this.guiTop += 10; - int yoffset = (int) ((double) this.ySize * 0.02); - GuiMenuTopButton top; - this.addTopButton(top = new GuiMenuTopButton(0, this.guiLeft + 4, this.guiTop - 17, "gui.settings")); - int topXoffset = 0; - int topYoffset = 0; - - - if (this.scriptHandler.container != null) { - this.addTopButton(top = new GuiMenuTopButton(1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, "Script")); - - } else { - this.addTopButton(new GuiMenuTopButton(this.scriptLimit, top.xPosition + top.width, top.yPosition, "+")); - } - - top = this.getTopButton(this.activeTab); - if (top == null) { - this.activeTab = 0; - top = this.getTopButton(0); - } - - top.active = true; - if (this.activeTab == 1) { - GuiCustomScroll hooks = new GuiCustomScroll(this, 1); - hooks.allowUserInput = false; - hooks.setSize(108, 198); - hooks.guiLeft = this.guiLeft - 110; - hooks.guiTop = this.guiTop + 14; - - hooks.setUnsortedList(this.hookList); - this.addScroll(hooks); - GuiNpcLabel hookLabel = new GuiNpcLabel(0, "script.hooks", hooks.guiLeft, this.guiTop + 5); - hookLabel.color = 11184810; - this.addLabel(hookLabel); - ScriptContainer container = this.scriptHandler.container; - if (textArea == null) - textArea = new GuiScriptTextArea(this, 2, this.guiLeft + 1 + yoffset, this.guiTop + yoffset, this.xSize - 108 - yoffset, (int) ((double) this.ySize * 0.96) - yoffset * 2, container == null ? "" : container.script); - else - textArea.init(this.guiLeft + 1 + yoffset, this.guiTop + yoffset, this.xSize - 108 - yoffset, (int) ((double) this.ySize * 0.96) - yoffset * 2, container == null ? "" : container.script); - textArea.enableCodeHighlighting(); - textArea.setListener(this); - this.closeOnEsc(textArea::closeOnEsc); - this.addTextField(textArea); - - int left1 = this.guiLeft + this.xSize - 104; - this.addButton(new GuiNpcButton(102, left1, this.guiTop + yoffset, 60, 20, "gui.clear")); - this.addButton(new GuiNpcButton(101, left1 + 61, this.guiTop + yoffset, 60, 20, "gui.paste")); - this.addButton(new GuiNpcButton(100, left1, this.guiTop + 21 + yoffset, 60, 20, "gui.copy")); - this.addButton(new GuiNpcButton(105, left1 + 61, this.guiTop + 21 + yoffset, 60, 20, "gui.remove")); - - this.addButton(new GuiNpcButton(107, left1, this.guiTop + 66 + yoffset, 80, 20, "script.loadscript")); - this.getButton(107).enabled = false; - - GuiCustomScroll scroll = (new GuiCustomScroll(this, 0)).setUnselectable(); - scroll.setSize(100, (int) ((double) this.ySize * 0.54) - yoffset * 2); - scroll.guiLeft = left1; - scroll.guiTop = this.guiTop + 88 + yoffset; - if (container != null) { - scroll.setList(container.scripts); - } - - this.addScroll(scroll); - } else { - GuiNpcTextArea var8 = new GuiNpcTextArea(2, this, this.guiLeft + 4 + yoffset, this.guiTop + 6 + yoffset, this.xSize - 160 - yoffset, (int) ((float) this.ySize * 0.92F) - yoffset * 2, this.getConsoleText()); - var8.enabled = false; - this.addTextField(var8); - int var9 = this.guiLeft + this.xSize - 150; - this.addButton(new GuiNpcButton(100, var9, this.guiTop + 125, 60, 20, "gui.copy")); - this.addButton(new GuiNpcButton(102, var9, this.guiTop + 146, 60, 20, "gui.clear")); - this.addLabel(new GuiNpcLabel(1, "script.language", var9, this.guiTop + 15)); - this.addButton(new GuiNpcButton(103, var9 + 60, this.guiTop + 10, 80, 20, this.languages.keySet().toArray(new String[this.languages.keySet().size()]), this.getScriptIndex())); - this.getButton(103).enabled = !this.languages.isEmpty(); - this.addLabel(new GuiNpcLabel(2, "gui.enabled", var9, this.guiTop + 36)); - this.addButton(new GuiNpcButton(104, var9 + 60, this.guiTop + 31, 50, 20, new String[]{"gui.no", "gui.yes"}, this.scriptHandler.getEnabled() ? 1 : 0)); - - this.addButton(new GuiNpcButton(109, var9, this.guiTop + 78, 80, 20, "gui.website")); - this.addButton(new GuiNpcButton(112, var9 + 81, this.guiTop + 78, 80, 20, "gui.forum")); - this.addButton(new GuiNpcButton(110, var9, this.guiTop + 99, 80, 20, "script.apidoc")); - this.addButton(new GuiNpcButton(111, var9 + 81, this.guiTop + 99, 80, 20, "script.apisrc")); - } - - this.xSize = 420; - this.ySize = 256; + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.ITEM; } - public void customScrollClicked(int i, int j, int k, GuiCustomScroll scroll) { - String hook = scroll.getSelected(); - if (this.previousHookClicked.equals(hook)) { - String addString = ""; - if (!this.getTextField(2).getText().isEmpty()) { - addString = addString + "\n"; - } - - addString = addString + "function " + hook + "(event) {\n \n}\n"; - this.getTextField(2).setText(this.getTextField(2).getText() + addString); - this.previousHookClicked = ""; - } else { - this.previousHookClicked = hook; - } - - } - - public void unFocused(GuiNpcTextField textfield) { - } - - private String getConsoleText() { - Map map = this.scriptHandler.getConsoleText(); - StringBuilder builder = new StringBuilder(); - Iterator var3 = map.entrySet().iterator(); - - while (var3.hasNext()) { - Map.Entry entry = (Map.Entry) var3.next(); - builder.insert(0, new Date((Long) entry.getKey()) + (String) entry.getValue() + "\n"); - } - - return builder.toString(); - } - - private int getScriptIndex() { - int i = 0; - - for (Iterator var2 = this.languages.keySet().iterator(); var2.hasNext(); ++i) { - String language = (String) var2.next(); - if (language.equalsIgnoreCase(this.scriptHandler.getLanguage())) { - return i; - } - } - - return 0; - } - - public void confirmClicked(boolean flag, int i) { - if (flag) { - if (i == 0) { - this.openLink("https://www.curseforge.com/minecraft/mc-mods/customnpc-plus"); - } - - if (i == 1) { - this.openLink("https://kamkeel.github.io/CustomNPC-Plus/"); - } - - if (i == 2) { - this.openLink("https://kamkeel.github.io/CustomNPC-Plus/"); - } - - if (i == 3) { - this.openLink("http://www.minecraftforge.net/forum/index.php/board,122.0.html"); - } - - if (i == 10) { - this.scriptHandler.container = null; - this.activeTab = 0; - } - - if (i == 101) { - this.getTextField(2).setText(NoppesStringUtils.getClipboardContents()); - this.setScript(); - } - - if (i == 102) { - if (this.activeTab == 1) { - ScriptContainer container = this.scriptHandler.container; - container.script = ""; - } else { - this.scriptHandler.clearConsole(); - } - - this.initGui(); - } - } - - this.displayGuiScreen(this); - } - - protected void actionPerformed(GuiButton guibutton) { - if (guibutton.id == 0) { - this.setScript(); - this.activeTab = 0; - this.initGui(); - } - - if (guibutton.id == this.scriptLimit) { - if (scriptHandler.container == null) - this.scriptHandler.container = new ScriptContainer(this.scriptHandler); - else - this.setScript(); - this.activeTab = 1; - this.initGui(); - } - - if (guibutton.id == 109) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://kamkeel.github.io/CustomNPC-Plus/", 0, true)); - } - - if (guibutton.id == 110) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://github.com/KAMKEEL/CustomNPC-Plus-API", 1, true)); - } - - if (guibutton.id == 111) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://github.com/Noppes/CustomNPCsAPI", 2, true)); - } - - if (guibutton.id == 112) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "http://www.minecraftforge.net/forum/index.php/board,122.0.html", 3, true)); - } - - if (guibutton.id == 100) { - NoppesStringUtils.setClipboardContents(this.getTextField(2).getText()); - } - - if (guibutton.id == 101) { - GuiYesNo guiyesno = new GuiYesNo(this, StatCollector.translateToLocal("gui.paste"), StatCollector.translateToLocal("gui.sure"), 101); - this.displayGuiScreen(guiyesno); - } - - GuiYesNo container1; - if (guibutton.id == 102) { - container1 = new GuiYesNo(this, StatCollector.translateToLocal("gui.clear"), StatCollector.translateToLocal("gui.sure"), 102); - this.displayGuiScreen(container1); - } - - if (guibutton.id == 103) { - this.scriptHandler.setLanguage(guibutton.displayString); - } - - if (guibutton.id == 104) { - this.scriptHandler.setEnabled(((GuiNpcButton) guibutton).getValue() == 1); - } - - if (guibutton.id == 105) { - container1 = new GuiYesNo(this, "", ((GuiNpcButton) guibutton).displayString, 10); - this.displayGuiScreen(container1); - } - - if (guibutton.id == 107) { - ScriptContainer container = this.scriptHandler.container; - if (container == null) { - container = new ScriptContainer(this.scriptHandler); - this.scriptHandler.container = container; - } - -// this.setSubGui(new EventGuiScriptList((List)this.languages.get(this.script.getLanguage()), container)); - } - - } - - private void setScript() { - if (this.activeTab == 1) { - ScriptContainer container = this.scriptHandler.container; - if (container == null) { - container = new ScriptContainer(this.scriptHandler); - this.scriptHandler.container = container; - } - - String text = this.getTextField(2).getText(); - text = text.replace("\r\n", "\n"); - text = text.replace("\r", "\n"); - container.script = text; - } - - } - - public void setGuiData(NBTTagCompound compound) { - if (compound.hasKey("LoadComplete")) { - loaded = true; - return; - } - - if (!compound.hasKey("Tab")) { - this.scriptHandler.setLanguage(compound.getString("ScriptLanguage")); - this.scriptHandler.setEnabled(compound.getBoolean("ScriptEnabled")); - this.copiedSetGuiData(compound); - } else { - int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(this.scriptHandler); - container.readFromNBT(compound.getCompoundTag("Script")); - this.scriptHandler.container = container; - this.initGui(); - } - - } - - private void copiedSetGuiData(NBTTagCompound compound) { - NBTTagList data = compound.getTagList("Languages", 10); - HashMap languages = new HashMap(); - - for (int i = 0; i < data.tagCount(); ++i) { - NBTTagCompound comp = data.getCompoundTagAt(i); - ArrayList scripts = new ArrayList(); - NBTTagList list = comp.getTagList("Scripts", 8); - - for (int j = 0; j < list.tagCount(); ++j) { - scripts.add(list.getStringTagAt(j)); - } - - languages.put(comp.getString("Language"), scripts); - } - - this.languages = languages; - this.initGui(); - } - - public void save() { - if (loaded) { - this.setScript(); - - List containers = this.scriptHandler.getScripts(); - for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); - LinkedItemScriptPacket.Save(linkedItem.id, i, containers.size(), container.writeToNBT(new NBTTagCompound())); - } - NBTTagCompound scriptData = new NBTTagCompound(); - scriptData.setString("ScriptLanguage", this.scriptHandler.getLanguage()); - scriptData.setBoolean("ScriptEnabled", this.scriptHandler.getEnabled()); - scriptData.setTag("ScriptConsole", NBTTags.NBTLongStringMap(this.scriptHandler.getConsoleText())); - - LinkedItemScriptPacket.Save(linkedItem.id, -1, containers.size(), scriptData); - } - } - - public void textUpdate(String text) { - ScriptContainer container = this.scriptHandler.container; - if (container != null) { - container.script = text; - } - - } - - public void saveText(String text) { - ScriptContainer container = this.scriptHandler.container; - if (container != null) { - container.script = text; - } - - this.initGui(); + protected void setHandlerContainer(ScriptContainer container) { + ((LinkedItemScript) handler).container = container; } @Override - public void close() { - this.save(); - parent.setWorldAndResolution(mc, width, height); - parent.initGui(); - mc.currentScreen = parent; + public void setGuiData(NBTTagCompound compound) { + setGuiDataWithOldContainer(compound); + } + + protected void sendSavePacket(int index, int totalCount, NBTTagCompound scriptNBT) { + LinkedItemScriptPacket.Save(linkedItem.id, index, totalCount, scriptNBT); + } + + @Override + public void save() { + saveWithPackets(); } } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java index 198e7af16..d401bc274 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java @@ -1,70 +1,27 @@ package noppes.npcs.client.gui.script; import kamkeel.npcs.network.packets.request.script.RecipeScriptPacket; -import net.minecraft.client.gui.GuiButton; -import net.minecraft.client.gui.GuiConfirmOpenLink; -import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.StatCollector; -import noppes.npcs.NBTTags; -import noppes.npcs.NoppesStringUtils; import noppes.npcs.client.gui.global.GuiNpcManageRecipes; -import noppes.npcs.client.gui.util.GuiCustomScroll; -import noppes.npcs.client.gui.util.GuiMenuTopButton; -import noppes.npcs.client.gui.util.GuiNPCInterface; -import noppes.npcs.client.gui.util.GuiNpcButton; -import noppes.npcs.client.gui.util.GuiNpcLabel; -import noppes.npcs.client.gui.util.GuiNpcTextArea; -import noppes.npcs.client.gui.util.GuiNpcTextField; -import noppes.npcs.client.gui.util.GuiScriptTextArea; -import noppes.npcs.client.gui.util.ICustomScrollListener; -import noppes.npcs.client.gui.util.IGuiData; -import noppes.npcs.client.gui.util.IJTextAreaListener; -import noppes.npcs.client.gui.util.ITextChangeListener; -import noppes.npcs.client.gui.util.ITextfieldListener; -import noppes.npcs.api.handler.IScriptHookHandler; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.RecipeAnvil; import noppes.npcs.controllers.data.RecipeCarpentry; import noppes.npcs.controllers.data.RecipeScript; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +public class GuiScriptRecipe extends GuiScriptInterface { -public class GuiScriptRecipe extends GuiNPCInterface implements GuiYesNoCallback, IGuiData, ITextChangeListener, ICustomScrollListener, IJTextAreaListener, ITextfieldListener { - private int activeTab = 0; - public Map> languages = new HashMap(); - private final int scriptLimit = 1; - public List hookList = new ArrayList(); - public String previousHookClicked = ""; - - public final GuiNpcManageRecipes parent; public final int recipeId; public final boolean anvil; - private final RecipeScript scriptHandler; - boolean loaded = false; - - private GuiScriptTextArea textArea; - public GuiScriptRecipe(GuiNpcManageRecipes parent, RecipeCarpentry recipe) { - this.drawDefaultBackground = true; - this.closeOnEsc = true; - this.xSize = 420; - this.setBackground("menubg.png"); - + super(); this.parent = parent; - - this.scriptHandler = new RecipeScript(); + this.handler = new RecipeScript(); this.anvil = false; this.recipeId = recipe.id; + this.singleContainer = true; this.hookList = new ArrayList<>(ScriptHookController.Instance.getAllHooks(IScriptHookHandler.CONTEXT_RECIPE)); @@ -72,14 +29,9 @@ public class GuiScriptRecipe extends GuiNPCInterface implements GuiYesNoCallback } public GuiScriptRecipe(GuiNpcManageRecipes parent, RecipeAnvil recipe) { - this.drawDefaultBackground = true; - this.closeOnEsc = true; - this.xSize = 420; - this.setBackground("menubg.png"); - + super(); this.parent = parent; - - this.scriptHandler = new RecipeScript(); + this.handler = new RecipeScript(); this.anvil = true; this.recipeId = recipe.id; @@ -88,355 +40,26 @@ public class GuiScriptRecipe extends GuiNPCInterface implements GuiYesNoCallback RecipeScriptPacket.Get(true, recipeId); } - public void initGui() { - this.ySize = (int) ((double) this.xSize * 0.56); - if ((double) this.ySize > (double) this.height * 0.95) { - this.ySize = (int) ((double) this.height * 0.95); - this.xSize = (int) ((double) this.ySize / 0.56); - } - - this.bgScale = (float) this.xSize / 400.0F; - super.initGui(); - this.guiTop += 10; - int yoffset = (int) ((double) this.ySize * 0.02); - GuiMenuTopButton top; - this.addTopButton(top = new GuiMenuTopButton(0, this.guiLeft + 4, this.guiTop - 17, "gui.settings")); - int topXoffset = 0; - int topYoffset = 0; - - if (this.scriptHandler.container != null) { - this.addTopButton(top = new GuiMenuTopButton(1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, "Script")); - - } else { - this.addTopButton(new GuiMenuTopButton(this.scriptLimit, top.xPosition + top.width, top.yPosition, "+")); - } - - top = this.getTopButton(this.activeTab); - if (top == null) { - this.activeTab = 0; - top = this.getTopButton(0); - } - - top.active = true; - if (this.activeTab == 1) { - GuiCustomScroll hooks = new GuiCustomScroll(this, 1); - hooks.allowUserInput = false; - hooks.setSize(108, 198); - hooks.guiLeft = this.guiLeft - 110; - hooks.guiTop = this.guiTop + 14; - - hooks.setUnsortedList(this.hookList); - this.addScroll(hooks); - GuiNpcLabel hookLabel = new GuiNpcLabel(0, "script.hooks", hooks.guiLeft, this.guiTop + 5); - hookLabel.color = 11184810; - this.addLabel(hookLabel); - ScriptContainer container = this.scriptHandler.container; - if (textArea == null) - textArea = new GuiScriptTextArea(this, 2, this.guiLeft + 1 + yoffset, this.guiTop + yoffset, this.xSize - 108 - yoffset, (int) ((double) this.ySize * 0.96) - yoffset * 2, container == null ? "" : container.script); - else - textArea.init(this.guiLeft + 1 + yoffset, this.guiTop + yoffset, this.xSize - 108 - yoffset, (int) ((double) this.ySize * 0.96) - yoffset * 2, container == null ? "" : container.script); - textArea.enableCodeHighlighting(); - textArea.setListener(this); - this.closeOnEsc(textArea::closeOnEsc); - this.addTextField(textArea); - - int left1 = this.guiLeft + this.xSize - 104; - this.addButton(new GuiNpcButton(102, left1, this.guiTop + yoffset, 60, 20, "gui.clear")); - this.addButton(new GuiNpcButton(101, left1 + 61, this.guiTop + yoffset, 60, 20, "gui.paste")); - this.addButton(new GuiNpcButton(100, left1, this.guiTop + 21 + yoffset, 60, 20, "gui.copy")); - this.addButton(new GuiNpcButton(105, left1 + 61, this.guiTop + 21 + yoffset, 60, 20, "gui.remove")); - - this.addButton(new GuiNpcButton(107, left1, this.guiTop + 66 + yoffset, 80, 20, "script.loadscript")); - this.getButton(107).enabled = false; - - GuiCustomScroll scroll = (new GuiCustomScroll(this, 0)).setUnselectable(); - scroll.setSize(100, (int) ((double) this.ySize * 0.54) - yoffset * 2); - scroll.guiLeft = left1; - scroll.guiTop = this.guiTop + 88 + yoffset; - if (container != null) { - scroll.setList(container.scripts); - } - - this.addScroll(scroll); - } else { - GuiNpcTextArea var8 = new GuiNpcTextArea(2, this, this.guiLeft + 4 + yoffset, this.guiTop + 6 + yoffset, this.xSize - 160 - yoffset, (int) ((float) this.ySize * 0.92F) - yoffset * 2, this.getConsoleText()); - var8.enabled = false; - this.addTextField(var8); - int var9 = this.guiLeft + this.xSize - 150; - this.addButton(new GuiNpcButton(100, var9, this.guiTop + 125, 60, 20, "gui.copy")); - this.addButton(new GuiNpcButton(102, var9, this.guiTop + 146, 60, 20, "gui.clear")); - this.addLabel(new GuiNpcLabel(1, "script.language", var9, this.guiTop + 15)); - this.addButton(new GuiNpcButton(103, var9 + 60, this.guiTop + 10, 80, 20, this.languages.keySet().toArray(new String[this.languages.keySet().size()]), this.getScriptIndex())); - this.getButton(103).enabled = !this.languages.isEmpty(); - this.addLabel(new GuiNpcLabel(2, "gui.enabled", var9, this.guiTop + 36)); - this.addButton(new GuiNpcButton(104, var9 + 60, this.guiTop + 31, 50, 20, new String[]{"gui.no", "gui.yes"}, this.scriptHandler.getEnabled() ? 1 : 0)); - - this.addButton(new GuiNpcButton(109, var9, this.guiTop + 78, 80, 20, "gui.website")); - this.addButton(new GuiNpcButton(112, var9 + 81, this.guiTop + 78, 80, 20, "gui.forum")); - this.addButton(new GuiNpcButton(110, var9, this.guiTop + 99, 80, 20, "script.apidoc")); - this.addButton(new GuiNpcButton(111, var9 + 81, this.guiTop + 99, 80, 20, "script.apisrc")); - } - - this.xSize = 420; - this.ySize = 256; + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.GLOBAL; } - public void customScrollClicked(int i, int j, int k, GuiCustomScroll scroll) { - String hook = scroll.getSelected(); - if (this.previousHookClicked.equals(hook)) { - String addString = ""; - if (!this.getTextField(2).getText().isEmpty()) { - addString = addString + "\n"; - } - - addString = addString + "function " + hook + "(event) {\n \n}\n"; - this.getTextField(2).setText(this.getTextField(2).getText() + addString); - this.previousHookClicked = ""; - } else { - this.previousHookClicked = hook; - } - - } - - public void unFocused(GuiNpcTextField textfield) { - } - - private String getConsoleText() { - Map map = this.scriptHandler.getConsoleText(); - StringBuilder builder = new StringBuilder(); - Iterator var3 = map.entrySet().iterator(); - - while (var3.hasNext()) { - Map.Entry entry = (Map.Entry) var3.next(); - builder.insert(0, new Date((Long) entry.getKey()) + (String) entry.getValue() + "\n"); - } - - return builder.toString(); - } - - private int getScriptIndex() { - int i = 0; - - for (Iterator var2 = this.languages.keySet().iterator(); var2.hasNext(); ++i) { - String language = (String) var2.next(); - if (language.equalsIgnoreCase(this.scriptHandler.getLanguage())) { - return i; - } - } - - return 0; - } - - public void confirmClicked(boolean flag, int i) { - if (flag) { - if (i == 0) { - this.openLink("https://www.curseforge.com/minecraft/mc-mods/customnpc-plus"); - } - - if (i == 1) { - this.openLink("https://kamkeel.github.io/CustomNPC-Plus/"); - } - - if (i == 2) { - this.openLink("https://kamkeel.github.io/CustomNPC-Plus/"); - } - - if (i == 3) { - this.openLink("http://www.minecraftforge.net/forum/index.php/board,122.0.html"); - } - - if (i == 10) { - this.scriptHandler.container = null; - this.activeTab = 0; - } - - if (i == 101) { - this.getTextField(2).setText(NoppesStringUtils.getClipboardContents()); - this.setScript(); - } - - if (i == 102) { - if (this.activeTab == 1) { - ScriptContainer container = this.scriptHandler.container; - container.script = ""; - } else { - this.scriptHandler.clearConsole(); - } - - this.initGui(); - } - } - - this.displayGuiScreen(this); - } - - protected void actionPerformed(GuiButton guibutton) { - if (guibutton.id == 0) { - this.setScript(); - this.activeTab = 0; - this.initGui(); - } - - if (guibutton.id == this.scriptLimit) { - if (scriptHandler.container == null) - this.scriptHandler.container = new ScriptContainer(this.scriptHandler); - else - this.setScript(); - this.activeTab = 1; - this.initGui(); - } - - if (guibutton.id == 109) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://kamkeel.github.io/CustomNPC-Plus/", 0, true)); - } - - if (guibutton.id == 110) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://github.com/KAMKEEL/CustomNPC-Plus-API", 1, true)); - } - - if (guibutton.id == 111) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "https://github.com/Noppes/CustomNPCsAPI", 2, true)); - } - - if (guibutton.id == 112) { - this.displayGuiScreen(new GuiConfirmOpenLink(this, "http://www.minecraftforge.net/forum/index.php/board,122.0.html", 3, true)); - } - - if (guibutton.id == 100) { - NoppesStringUtils.setClipboardContents(this.getTextField(2).getText()); - } - - if (guibutton.id == 101) { - GuiYesNo guiyesno = new GuiYesNo(this, StatCollector.translateToLocal("gui.paste"), StatCollector.translateToLocal("gui.sure"), 101); - this.displayGuiScreen(guiyesno); - } - - GuiYesNo container1; - if (guibutton.id == 102) { - container1 = new GuiYesNo(this, StatCollector.translateToLocal("gui.clear"), StatCollector.translateToLocal("gui.sure"), 102); - this.displayGuiScreen(container1); - } - - if (guibutton.id == 103) { - this.scriptHandler.setLanguage(guibutton.displayString); - } - - if (guibutton.id == 104) { - this.scriptHandler.setEnabled(((GuiNpcButton) guibutton).getValue() == 1); - } - - if (guibutton.id == 105) { - container1 = new GuiYesNo(this, "", ((GuiNpcButton) guibutton).displayString, 10); - this.displayGuiScreen(container1); - } - - if (guibutton.id == 107) { - ScriptContainer container = this.scriptHandler.container; - if (container == null) { - container = new ScriptContainer(this.scriptHandler); - this.scriptHandler.container = container; - } - -// this.setSubGui(new EventGuiScriptList((List)this.languages.get(this.script.getLanguage()), container)); - } - - } - - private void setScript() { - if (this.activeTab == 1) { - ScriptContainer container = this.scriptHandler.container; - if (container == null) { - container = new ScriptContainer(this.scriptHandler); - this.scriptHandler.container = container; - } - - String text = this.getTextField(2).getText(); - text = text.replace("\r\n", "\n"); - text = text.replace("\r", "\n"); - container.script = text; - } - - } - - public void setGuiData(NBTTagCompound compound) { - if (compound.hasKey("LoadComplete")) { - loaded = true; - return; - } - - if (!compound.hasKey("Tab")) { - this.scriptHandler.setLanguage(compound.getString("ScriptLanguage")); - this.scriptHandler.setEnabled(compound.getBoolean("ScriptEnabled")); - this.copiedSetGuiData(compound); - } else { - int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(this.scriptHandler); - container.readFromNBT(compound.getCompoundTag("Script")); - this.scriptHandler.container = container; - this.initGui(); - } - } - - private void copiedSetGuiData(NBTTagCompound compound) { - NBTTagList data = compound.getTagList("Languages", 10); - HashMap languages = new HashMap(); - - for (int i = 0; i < data.tagCount(); ++i) { - NBTTagCompound comp = data.getCompoundTagAt(i); - ArrayList scripts = new ArrayList(); - NBTTagList list = comp.getTagList("Scripts", 8); - - for (int j = 0; j < list.tagCount(); ++j) { - scripts.add(list.getStringTagAt(j)); - } - - languages.put(comp.getString("Language"), scripts); - } - - this.languages = languages; - this.initGui(); - } - - public void save() { - if (loaded) { - this.setScript(); - - List containers = this.scriptHandler.getScripts(); - for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); - RecipeScriptPacket.Save(anvil, recipeId, i, containers.size(), container.writeToNBT(new NBTTagCompound())); - } - NBTTagCompound scriptData = new NBTTagCompound(); - scriptData.setString("ScriptLanguage", this.scriptHandler.getLanguage()); - scriptData.setBoolean("ScriptEnabled", this.scriptHandler.getEnabled()); - scriptData.setTag("ScriptConsole", NBTTags.NBTLongStringMap(this.scriptHandler.getConsoleText())); - - RecipeScriptPacket.Save(anvil, recipeId, -1, containers.size(), scriptData); - } - } - - public void textUpdate(String text) { - ScriptContainer container = this.scriptHandler.container; - if (container != null) { - container.script = text; - } - - } - - public void saveText(String text) { - ScriptContainer container = this.scriptHandler.container; - if (container != null) { - container.script = text; - } - - this.initGui(); + protected void setHandlerContainer(ScriptContainer container) { + ((RecipeScript) handler).container = container; } @Override - public void close() { - this.save(); - parent.setWorldAndResolution(mc, width, height); - parent.initGui(); - mc.currentScreen = parent; + public void setGuiData(NBTTagCompound compound) { + setGuiDataWithOldContainer(compound); + } + + protected void sendSavePacket(int index, int totalCount, NBTTagCompound scriptNBT) { + RecipeScriptPacket.Save(anvil, recipeId, index, totalCount, scriptNBT); + } + + @Override + public void save() { + saveWithPackets(); } } From 1372127266e2e9d3757fa8e083748cf99d9de45a Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Mon, 12 Jan 2026 03:56:22 +0200 Subject: [PATCH 02/19] GuiScript now extends GuiScriptInterface + Full screen support --- .../noppes/npcs/client/gui/GuiScript.java | 329 ++++++++++-------- .../client/gui/script/GuiScriptInterface.java | 129 ++++--- 2 files changed, 259 insertions(+), 199 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/GuiScript.java b/src/main/java/noppes/npcs/client/gui/GuiScript.java index e710eef23..a8017222d 100644 --- a/src/main/java/noppes/npcs/client/gui/GuiScript.java +++ b/src/main/java/noppes/npcs/client/gui/GuiScript.java @@ -4,7 +4,6 @@ import kamkeel.npcs.network.packets.request.script.NPCScriptPacket; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiConfirmOpenLink; import net.minecraft.client.gui.GuiYesNo; -import net.minecraft.client.gui.GuiYesNoCallback; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.server.MinecraftServer; @@ -12,44 +11,77 @@ import net.minecraft.util.StatCollector; import noppes.npcs.NoppesStringUtils; import noppes.npcs.client.NoppesUtil; import noppes.npcs.client.gui.script.GuiNPCEventScripts; +import noppes.npcs.client.gui.script.GuiScriptInterface; import noppes.npcs.client.gui.util.*; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.DataScript; import noppes.npcs.entity.EntityNPCInterface; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; -public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCallback, ICustomScrollListener, IJTextAreaListener, ITextChangeListener { +/** + * NPC Script GUI - extends GuiScriptInterface but with unique behavior: + * - Uses scroll-based tab selection instead of top buttons + * - Shows settings/script toggle + * - Uses DataScript with getNPCScript(index) access pattern + * - Has console filtering by hook type + */ +public class GuiScript extends GuiScriptInterface { public boolean showScript = false; - private int activeTab = 0; public DataScript script; - public Map> languages = new HashMap>(); - + private static int activeConsole = 0; - boolean loaded = false; - - private Map textAreas = new HashMap<>(); public GuiScript(EntityNPCInterface npc) { - super(npc); - script = npc.script; - drawDefaultBackground = true; - closeOnEsc = true; - xSize = 420; - - setBackground("menubg.png"); + super(); + this.npc = npc; + this.script = npc.script; + this.handler = script; + this.useScrollTabs = true; + this.useSettingsToggle = true; + + // Initialize hook list for NPC scripts + hookList.add("script.init"); + hookList.add("script.update"); + hookList.add("script.interact"); + hookList.add("dialog.dialog"); + hookList.add("script.damaged"); + hookList.add("script.killed"); + hookList.add("script.attack"); + hookList.add("script.target"); + hookList.add("script.collide"); + hookList.add("script.kills"); + hookList.add("script.dialog_closed"); + hookList.add("script.timer"); + hookList.add("script.targetLost"); + hookList.add("script.projectileTick"); + hookList.add("script.projectileImpact"); + NPCScriptPacket.Get(); } + + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.NPC; + } + + @Override + protected int getActiveScriptIndex() { + return this.activeTab; + } + + @Override + protected ScriptContainer getCurrentContainer() { + return script.getNPCScript(activeTab); + } + @Override public void initGui() { super.initGui(); - guiTop += 10; + this.guiTop += 10; + + // ==================== TOP BUTTONS ==================== GuiMenuTopButton top; addTopButton(top = new GuiMenuTopButton(13, guiLeft + 4, guiTop - 17, "script.scripts")); addTopButton(new GuiMenuTopButton(16, guiLeft + (xSize - 102), guiTop - 17, "eventscript.eventScripts")); @@ -59,51 +91,86 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall top.active = !showScript; addTopButton(new GuiMenuTopButton(15, top, "gui.website")); - List list = new ArrayList(); - list.add("script.init"); - list.add("script.update"); - list.add("script.interact"); - list.add("dialog.dialog"); - list.add("script.damaged"); - list.add("script.killed"); - list.add("script.attack"); - list.add("script.target"); - list.add("script.collide"); - list.add("script.kills"); - list.add("script.dialog_closed"); - list.add("script.timer"); - list.add("script.targetLost"); - list.add("script.projectileTick"); - list.add("script.projectileImpact"); - if (showScript) { + initScriptView(); + } else { + initSettingsView(); + } + } + + private void initScriptView() { + ScriptContainer container = getCurrentContainer(); + + // ==================== CALCULATE VIEWPORT BOUNDS ==================== + int editorX, editorY, editorWidth, editorHeight; + + if (isFullscreen) { + // Fullscreen: viewport fills screen with configured padding + FullscreenConfig.paddingTop = 30; + FullscreenConfig.paddingBottom = 20; + FullscreenConfig.paddingLeft = 20; + FullscreenConfig.paddingRight = 20; + editorX = FullscreenConfig.paddingLeft; + editorY = FullscreenConfig.paddingTop; + editorWidth = this.width - FullscreenConfig.paddingLeft - FullscreenConfig.paddingRight; + editorHeight = this.height - FullscreenConfig.paddingTop - FullscreenConfig.paddingBottom; + } else { + // Normal: fixed layout with hooks on left + editorX = guiLeft + 74; + editorY = guiTop + 4; + editorWidth = 239; + editorHeight = 208; + } + + // ==================== HOOKS SCROLL (hidden in fullscreen) ==================== + if (!isFullscreen) { addLabel(new GuiNpcLabel(0, "script.hooks", guiLeft + 4, guiTop + 5)); + GuiCustomScroll hooks = new GuiCustomScroll(this, 1); hooks.setSize(68, 198); hooks.guiLeft = guiLeft + 4; hooks.guiTop = guiTop + 14; - hooks.setUnsortedList(list); + hooks.setUnsortedList(hookList); hooks.selected = activeTab; addScroll(hooks); + } - ScriptContainer container = script.getNPCScript(activeTab); + // ==================== SCRIPT TEXT AREA ==================== + int idx = getActiveScriptIndex(); + GuiScriptTextArea activeArea = getActiveScriptArea(); + if (activeArea == null) { + activeArea = new GuiScriptTextArea(this, 2, editorX, editorY, editorWidth, editorHeight, + container == null ? "" : container.script); + activeArea.setListener(this); + this.closeOnEsc(activeArea::closeOnEsc); + textAreas.put(idx, activeArea); + } else { + activeArea.init(editorX, editorY, editorWidth, editorHeight, + container == null ? "" : container.script); + } - int idx = this.activeTab; - GuiScriptTextArea activeArea = getActiveScriptArea(); - if (activeArea == null) { - activeArea = new GuiScriptTextArea(this, 2, guiLeft + 74, guiTop + 4, 239, 208, - container == null ? "" : container.script); - activeArea.setListener(this); - this.closeOnEsc(activeArea::closeOnEsc); - textAreas.put(idx, activeArea); - } else { - activeArea.init(guiLeft + 74, guiTop + 4, 239, 208, container == null ? "" : container.script); + activeArea.setLanguage(script.getLanguage()); + activeArea.setScriptContext(getScriptContext()); + + // Setup fullscreen key binding + GuiScriptTextArea.KEYS.FULLSCREEN.setTask(e -> { + if (e.isPress()) { + toggleFullscreen(); } + }); + + activeArea.enableCodeHighlighting(); + addTextField(activeArea); + + // Initialize fullscreen button + int scrollbarOffset = activeArea.hasVerticalScrollbar() ? -8 : -2; + fullscreenButton.initGui(editorX + editorWidth, editorY, scrollbarOffset); + // ==================== RIGHT PANEL BUTTONS (hidden in fullscreen) ==================== + if (!isFullscreen) { addButton(new GuiNpcButton(102, guiLeft + 315, guiTop + 4, 50, 20, "gui.clear")); addButton(new GuiNpcButton(101, guiLeft + 366, guiTop + 4, 50, 20, "gui.paste")); addButton(new GuiNpcButton(100, guiLeft + 315, guiTop + 25, 50, 20, "gui.copy")); - addButton(new GuiNpcButton(107, guiLeft + 315, guiTop + 70, 80, 20, "script.loadscript")); GuiCustomScroll scroll = new GuiCustomScroll(this, 0).setUnselectable(); @@ -113,74 +180,49 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall if (container != null) scroll.setList(container.scripts); addScroll(scroll); - } else { - addLabel(new GuiNpcLabel(0, "script.console", guiLeft + 4, guiTop + 16)); - getTopButton(14).active = true; - addTextField(new GuiNpcTextArea(2, this, guiLeft + 4, guiTop + 26, 226, 186, getConsoleText())); - getTextField(2).canEdit = false; - addButton(new GuiNpcButton(100, guiLeft + 232, guiTop + 170, 56, 20, "gui.copy")); - addButton(new GuiNpcButton(102, guiLeft + 232, guiTop + 192, 56, 20, "gui.clear")); - - List l = new ArrayList(); - l.add("All"); - l.addAll(list); - addButton(new GuiNpcButton(105, guiLeft + 60, guiTop + 4, 80, 20, l.toArray(new String[l.size()]), activeConsole)); - - addLabel(new GuiNpcLabel(1, "script.language", guiLeft + 232, guiTop + 30)); - addButton(new GuiNpcButton(103, guiLeft + 294, guiTop + 25, 80, 20, languages.keySet().toArray(new String[languages.keySet().size()]), getScriptIndex())); - getButton(103).enabled = languages.size() > 0; - - addLabel(new GuiNpcLabel(2, "gui.enabled", guiLeft + 232, guiTop + 53)); - addButton(new GuiNpcButton(104, guiLeft + 294, guiTop + 48, 50, 20, new String[]{"gui.no", "gui.yes"}, script.enabled ? 1 : 0)); - - if (MinecraftServer.getServer() != null) - addButton(new GuiNpcButton(106, guiLeft + 232, guiTop + 71, 150, 20, "script.openfolder")); } } + + private void initSettingsView() { + addLabel(new GuiNpcLabel(0, "script.console", guiLeft + 4, guiTop + 16)); + getTopButton(14).active = true; + + GuiNpcTextArea consoleArea = new GuiNpcTextArea(2, this, guiLeft + 4, guiTop + 26, 226, 186, getConsoleText()); + consoleArea.canEdit = false; + addTextField(consoleArea); + + addButton(new GuiNpcButton(100, guiLeft + 232, guiTop + 170, 56, 20, "gui.copy")); + addButton(new GuiNpcButton(102, guiLeft + 232, guiTop + 192, 56, 20, "gui.clear")); - private GuiScriptTextArea getActiveScriptArea() { - if (this.activeTab > 0) { - int idx = this.activeTab; - if (idx >= 0 && idx < textAreas.size()) - return textAreas.get(idx); - } - return null; + List consoleOptions = new ArrayList<>(); + consoleOptions.add("All"); + consoleOptions.addAll(hookList); + addButton(new GuiNpcButton(105, guiLeft + 60, guiTop + 4, 80, 20, + consoleOptions.toArray(new String[0]), activeConsole)); + + addLabel(new GuiNpcLabel(1, "script.language", guiLeft + 232, guiTop + 30)); + addButton(new GuiNpcButton(103, guiLeft + 294, guiTop + 25, 80, 20, + languages.keySet().toArray(new String[0]), getScriptIndex())); + getButton(103).enabled = languages.size() > 0; + + addLabel(new GuiNpcLabel(2, "gui.enabled", guiLeft + 232, guiTop + 53)); + addButton(new GuiNpcButton(104, guiLeft + 294, guiTop + 48, 50, 20, + new String[]{"gui.no", "gui.yes"}, script.enabled ? 1 : 0)); + + if (MinecraftServer.getServer() != null) + addButton(new GuiNpcButton(106, guiLeft + 232, guiTop + 71, 150, 20, "script.openfolder")); } @Override - public GuiNpcTextField getTextField(int id) { - if (id == 2) { - GuiScriptTextArea area = getActiveScriptArea(); - if (area != null) - return area; - } - return super.getTextField(id); - } - - private int getScriptIndex() { - int i = 0; - for (String language : languages.keySet()) { - if (language.equalsIgnoreCase(script.scriptLanguage)) - return i; - i++; - } - return 0; - } - - private String getConsoleText() { + protected String getConsoleText() { Map map = this.script.getOldConsoleText(); StringBuilder builder = new StringBuilder(); - Iterator var3 = map.entrySet().iterator(); - - while (var3.hasNext()) { - Map.Entry entry = (Map.Entry) var3.next(); - builder.insert(0, new Date((Long) entry.getKey()) + (String) entry.getValue() + "\n"); + for (Map.Entry entry : map.entrySet()) { + builder.insert(0, new Date(entry.getKey()) + entry.getValue() + "\n"); } - return builder.toString(); } - @Override public void confirmClicked(boolean result, int id) { NoppesUtil.openGUI(player, this); @@ -205,8 +247,6 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall } } } - - displayGuiScreen(this); } @@ -222,8 +262,7 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall initGui(); } if (guibutton.id == 15) { - GuiConfirmOpenLink guiyesno = new GuiConfirmOpenLink(this, "https://kamkeel.github.io/CustomNPC-Plus/", 0, true); - mc.displayGuiScreen(guiyesno); + displayGuiScreen(new GuiConfirmOpenLink(this, "https://kamkeel.github.io/CustomNPC-Plus/", 0, true)); } if (guibutton.id == 16) { close(); @@ -236,12 +275,12 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall NoppesStringUtils.setClipboardContents(getTextField(2).getText()); } if (guibutton.id == 101) { - GuiYesNo guiyesno = new GuiYesNo(this, StatCollector.translateToLocal("gui.paste"), StatCollector.translateToLocal("gui.sure"), 101); - displayGuiScreen(guiyesno); + displayGuiScreen(new GuiYesNo(this, StatCollector.translateToLocal("gui.paste"), + StatCollector.translateToLocal("gui.sure"), 101)); } if (guibutton.id == 102) { - GuiYesNo guiyesno = new GuiYesNo(this, StatCollector.translateToLocal("gui.clear"), StatCollector.translateToLocal("gui.sure"), 102); - displayGuiScreen(guiyesno); + displayGuiScreen(new GuiYesNo(this, StatCollector.translateToLocal("gui.clear"), + StatCollector.translateToLocal("gui.sure"), 102)); } if (guibutton.id == 103) { script.scriptLanguage = ((GuiNpcButton) guibutton).displayString; @@ -254,21 +293,20 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall initGui(); } if (guibutton.id == 106) { - // TODO: Uses ScriptController.Instance.dir (shared script repository); this GUI is gated behind the scripter tool - // and CustomNpcsPermissions.TOOL_SCRIPTER so only authorized editors touch the controller-backed scripts. NoppesUtil.openFolder(ScriptController.Instance.dir); } if (guibutton.id == 107) { - ScriptContainer container = script.getNPCScript(activeTab); + ScriptContainer container = getCurrentContainer(); if (container == null) script.setNPCScript(activeTab, container = new ScriptContainer(this.script)); setSubGui(new GuiScriptList(languages.get(script.scriptLanguage), container)); } } - private void setScript() { + @Override + protected void setScript() { if (showScript) { - ScriptContainer container = script.getNPCScript(activeTab); + ScriptContainer container = getCurrentContainer(); if (container == null) script.setNPCScript(activeTab, container = new ScriptContainer(this.script)); String text = getTextField(2).getText(); @@ -277,23 +315,31 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall container.script = text; } } + + @Override + public void mouseClicked(int mouseX, int mouseY, int mouseButton) { + // Check if click is within autocomplete menu bounds and consume it if so + GuiScriptTextArea activeArea = getActiveScriptArea(); + boolean isOverAutocomplete = activeArea != null + && activeArea.isPointOnAutocompleteMenu(mouseX, mouseY); + if (isOverAutocomplete) { + activeArea.mouseClicked(mouseX, mouseY, mouseButton); + return; + } + + // Check fullscreen button when in script view + if (showScript && !isOverAutocomplete + && fullscreenButton.mouseClicked(mouseX, mouseY, mouseButton)) { + return; + } + + super.mouseClicked(mouseX, mouseY, mouseButton); + } @Override public void setGuiData(NBTTagCompound compound) { script.readFromNBT(compound); - NBTTagList data = compound.getTagList("Languages", 10); - Map> languages = new HashMap>(); - for (int i = 0; i < data.tagCount(); i++) { - NBTTagCompound comp = data.getCompoundTagAt(i); - List scripts = new ArrayList(); - NBTTagList list = comp.getTagList("Scripts", 8); - for (int j = 0; j < list.tagCount(); j++) { - scripts.add(list.getStringTagAt(j)); - } - languages.put(comp.getString("Language"), scripts); - } - this.languages = languages; - initGui(); + loadLanguagesData(compound); loaded = true; } @@ -313,20 +359,5 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall initGui(); } } - - public void textUpdate(String text) { - ScriptContainer container = script.getNPCScript(activeTab); - if (container != null) - container.script = text; - } - - @Override - public void saveText(String text) { - ScriptContainer container = script.getNPCScript(activeTab); - if (container != null) - container.script = text; - initGui(); - } - } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 765f29f60..1df897ecc 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -41,14 +41,20 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb protected int activeTab = 0; public IScriptHandler handler; public Map> languages = new HashMap(); - private int scriptLimit = 1; + protected int scriptLimit = 1; public List hookList = new ArrayList(); protected boolean loaded = false; - private Map textAreas = new HashMap<>(); + protected Map textAreas = new HashMap<>(); protected GuiScreen parent; - public boolean singleContainer = false; + public boolean singleContainer = false; + + /** If true, uses scroll-based tab selection instead of top buttons */ + protected boolean useScrollTabs = false; + + /** If true, shows settings/script toggle instead of numbered tabs */ + protected boolean useSettingsToggle = false; // ==================== FULLSCREEN MODE ==================== /** Whether the editor viewport is currently in fullscreen mode */ @@ -94,48 +100,54 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb int yoffset = (int) ((double) this.ySize * 0.02D); // ==================== TAB BUTTONS ==================== - GuiMenuTopButton top; - int topButtonsX = isFullscreen && activeTab != 0 ? FullscreenConfig.paddingLeft : this.guiLeft + 4; - int topButtonsY = isFullscreen && activeTab != 0 ? FullscreenConfig.paddingTop - 20 : this.guiTop - 17; - this.addTopButton(top = new GuiMenuTopButton(0, topButtonsX, topButtonsY, "gui.settings")); + // Skip standard tab creation for GUIs that use custom toggle/scroll tabs + if (!useSettingsToggle) { + GuiMenuTopButton top; + int topButtonsX = isFullscreen && activeTab != 0 ? FullscreenConfig.paddingLeft : this.guiLeft + 4; + int topButtonsY = isFullscreen && activeTab != 0 ? FullscreenConfig.paddingTop - 20 : this.guiTop - 17; + this.addTopButton(top = new GuiMenuTopButton(0, topButtonsX, topButtonsY, "gui.settings")); - int topXoffset = 0; - int topYoffset = 0; - if(!singleContainer) { - for (int ta = 0; ta < this.handler.getScripts().size(); ++ta) { - if (ta % 20 == 0 && ta > 0) { - topYoffset -= 20; - topXoffset -= top.width + 20 * 22; + int topXoffset = 0; + int topYoffset = 0; + if(!singleContainer) { + for (int ta = 0; ta < this.handler.getScripts().size(); ++ta) { + if (ta % 20 == 0 && ta > 0) { + topYoffset -= 20; + topXoffset -= top.width + 20 * 22; + } + this.addTopButton(top = new GuiMenuTopButton(ta + 1, top.xPosition + top.width + topXoffset, + top.yPosition + topYoffset, ta + 1 + "")); + topXoffset = 0; + topYoffset = 0; + scriptLimit = ta + 2; } - this.addTopButton(top = new GuiMenuTopButton(ta + 1, top.xPosition + top.width + topXoffset, - top.yPosition + topYoffset, ta + 1 + "")); - topXoffset = 0; - topYoffset = 0; - scriptLimit = ta + 2; } + + if (singleContainer && getFirst() != null) + this.addTopButton( + top = new GuiMenuTopButton(1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, + "Script")); + else if (this.handler.getScripts().size() < 100) + this.addTopButton(new GuiMenuTopButton(scriptLimit, top.xPosition + top.width, top.yPosition, "+")); + + + top = this.getTopButton(this.activeTab); + if (top == null) { + this.activeTab = 0; + top = this.getTopButton(0); + } + top.active = true; } - if (singleContainer && getFirst() != null) - this.addTopButton( - top = new GuiMenuTopButton(1, top.xPosition + top.width + topXoffset, top.yPosition + topYoffset, - "Script")); - else if (this.handler.getScripts().size() < 100) - this.addTopButton(new GuiMenuTopButton(scriptLimit, top.xPosition + top.width, top.yPosition, "+")); - - - top = this.getTopButton(this.activeTab); - if (top == null) { - this.activeTab = 0; - top = this.getTopButton(0); - } - top.active = true; - // ==================== SCRIPT EDITOR TAB (activeTab > 0) ==================== - if (this.activeTab > 0) { - initScriptEditorTab(yoffset); - } else { - // ==================== SETTINGS TAB (activeTab == 0) ==================== - initSettingsTab(yoffset); + // Skip for GUIs that handle their own view initialization (useSettingsToggle) + if (!useSettingsToggle) { + if (this.activeTab > 0) { + initScriptEditorTab(yoffset); + } else { + // ==================== SETTINGS TAB (activeTab == 0) ==================== + initSettingsTab(yoffset); + } } this.xSize = 420; @@ -147,7 +159,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb * Handles both normal and fullscreen modes. */ private void initScriptEditorTab(int yoffset) { - ScriptContainer container = (ScriptContainer) this.handler.getScripts().get(this.activeTab - 1); + ScriptContainer container = getCurrentContainer(); // ==================== CALCULATE VIEWPORT BOUNDS ==================== int editorX, editorY, editorWidth, editorHeight; @@ -191,7 +203,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } // ==================== SCRIPT TEXT AREA ==================== - int idx = this.activeTab - 1; + int idx = getActiveScriptIndex(); GuiScriptTextArea activeArea = getActiveScriptArea(); if (activeArea == null) { activeArea = new GuiScriptTextArea(this, 2, editorX, editorY, editorWidth, editorHeight, @@ -390,11 +402,28 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } public GuiScriptTextArea getActiveScriptArea() { - if (this.activeTab > 0) { - int idx = this.activeTab - 1; - if (idx >= 0 && idx < textAreas.size()) - return textAreas.get(idx); - } + int idx = getActiveScriptIndex(); + if (idx >= 0 && textAreas.containsKey(idx)) + return textAreas.get(idx); + return null; + } + + /** + * Get the current script index for text area storage. + * Override in subclasses with different tab logic. + */ + protected int getActiveScriptIndex() { + return this.activeTab - 1; + } + + /** + * Get the current script container. + * Override in subclasses with different container access patterns. + */ + protected ScriptContainer getCurrentContainer() { + int idx = getActiveScriptIndex(); + if (idx >= 0 && idx < this.handler.getScripts().size()) + return this.handler.getScripts().get(idx); return null; } @@ -500,8 +529,8 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } protected void setScript() { - if (this.activeTab > 0) { - ScriptContainer container = (ScriptContainer) this.handler.getScripts().get(this.activeTab - 1); + if (this.activeTab > 0 || useScrollTabs) { + ScriptContainer container = getCurrentContainer(); if (container == null) { container = new ScriptContainer(this.handler); if (singleContainer) @@ -644,7 +673,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } public void textUpdate(String text) { - ScriptContainer container = (ScriptContainer) this.handler.getScripts().get(this.activeTab - 1); + ScriptContainer container = getCurrentContainer(); if (container != null) { container.script = text; } @@ -655,7 +684,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb @Override //NEVER USED public void saveText(String text) { - ScriptContainer container = handler.getScripts().get(activeTab ); //activeTab - 1? + ScriptContainer container = getCurrentContainer(); if (container != null) container.script = text; initGui(); From c3e032dcf2355b4cf129aae33aeece0013e40ff2 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 17:34:14 +0200 Subject: [PATCH 03/19] Abstracted ScriptContainer & JaninoScript to IScriptUnit + global implementation --- .../java/kamkeel/npcs/network/PacketUtil.java | 5 +- .../script/item/ItemScriptErrorPacket.java | 10 +- src/main/java/noppes/npcs/NBTTags.java | 16 +- .../npcs/blocks/tiles/TileScripted.java | 21 ++- .../client/gui/script/GuiNPCEventScripts.java | 5 +- .../client/gui/script/GuiScriptAllNPCs.java | 5 +- .../client/gui/script/GuiScriptForge.java | 5 +- .../client/gui/script/GuiScriptInterface.java | 31 ++-- .../client/gui/script/GuiScriptPlayers.java | 7 +- .../npcs/controllers/ScriptContainer.java | 73 +++++++- .../npcs/controllers/data/DataScript.java | 24 +-- .../npcs/controllers/data/EffectScript.java | 34 ++-- .../controllers/data/ForgeDataScript.java | 40 +++-- .../controllers/data/GlobalNPCDataScript.java | 40 +++-- .../npcs/controllers/data/IScriptHandler.java | 5 +- .../npcs/controllers/data/IScriptUnit.java | 117 +++++++++++++ .../controllers/data/LinkedItemScript.java | 32 ++-- .../controllers/data/PlayerDataScript.java | 69 ++++---- .../npcs/controllers/data/RecipeScript.java | 19 +- .../java/noppes/npcs/janino/JaninoScript.java | 163 ++++++++++++++---- .../npcs/scripted/item/ScriptCustomItem.java | 17 +- 21 files changed, 518 insertions(+), 220 deletions(-) create mode 100644 src/main/java/noppes/npcs/controllers/data/IScriptUnit.java diff --git a/src/main/java/kamkeel/npcs/network/PacketUtil.java b/src/main/java/kamkeel/npcs/network/PacketUtil.java index f262bce45..cb2881eb8 100644 --- a/src/main/java/kamkeel/npcs/network/PacketUtil.java +++ b/src/main/java/kamkeel/npcs/network/PacketUtil.java @@ -15,6 +15,7 @@ import noppes.npcs.NBTTags; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptHandler; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.items.ItemNpcTool; import java.io.IOException; @@ -221,9 +222,9 @@ public class PacketUtil { compound.setTag("Languages", ScriptController.Instance.nbtLanguages()); compound.setTag("ScriptConsole", NBTTags.NBTLongStringMap(data.getConsoleText())); GuiDataPacket.sendGuiData(player, compound); - List containers = data.getScripts(); + List containers = data.getScripts(); for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); + IScriptUnit container = containers.get(i); NBTTagCompound tabCompound = new NBTTagCompound(); tabCompound.setInteger("Tab", i); tabCompound.setTag("Script", container.writeToNBT(new NBTTagCompound())); diff --git a/src/main/java/kamkeel/npcs/network/packets/request/script/item/ItemScriptErrorPacket.java b/src/main/java/kamkeel/npcs/network/packets/request/script/item/ItemScriptErrorPacket.java index b4a8c619e..c1a7c74c5 100644 --- a/src/main/java/kamkeel/npcs/network/packets/request/script/item/ItemScriptErrorPacket.java +++ b/src/main/java/kamkeel/npcs/network/packets/request/script/item/ItemScriptErrorPacket.java @@ -16,7 +16,7 @@ import noppes.npcs.CustomNpcsPermissions; import noppes.npcs.NBTTags; import noppes.npcs.api.item.IItemStack; import noppes.npcs.config.ConfigScript; -import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.item.ScriptCustomItem; @@ -72,10 +72,10 @@ public final class ItemScriptErrorPacket extends AbstractPacket { if (requestedAction == Action.GET) { TreeMap map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : ((ScriptCustomItem) iw).scripts) { + for (IScriptUnit script : ((ScriptCustomItem) iw).scripts) { ++tab; - for (Map.Entry longStringEntry : script.console.entrySet()) { + for (Map.Entry longStringEntry : script.getConsole().entrySet()) { map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + longStringEntry.getValue()); } } @@ -84,8 +84,8 @@ public final class ItemScriptErrorPacket extends AbstractPacket { compound.setTag("ItemScriptConsole", NBTTags.NBTLongStringMap(map)); GuiDataPacket.sendGuiData((EntityPlayerMP) player, compound); } else { - for (ScriptContainer script : ((ScriptCustomItem) iw).scripts) { - script.console.clear(); + for (IScriptUnit script : ((ScriptCustomItem) iw).scripts) { + script.clearConsole(); } } } diff --git a/src/main/java/noppes/npcs/NBTTags.java b/src/main/java/noppes/npcs/NBTTags.java index ebf30ab94..21e751f11 100644 --- a/src/main/java/noppes/npcs/NBTTags.java +++ b/src/main/java/noppes/npcs/NBTTags.java @@ -8,6 +8,7 @@ import net.minecraft.nbt.NBTTagInt; import net.minecraft.nbt.NBTTagList; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.data.IScriptHandler; +import noppes.npcs.controllers.data.IScriptUnit; import java.util.ArrayList; import java.util.HashMap; @@ -540,8 +541,8 @@ public class NBTTags { } } - public static List GetScriptOld(NBTTagList list, IScriptHandler handler) { - ArrayList scripts = new ArrayList(); + public static List GetScriptOld(NBTTagList list, IScriptHandler handler) { + ArrayList scripts = new ArrayList<>(); for (int i = 0; i < list.tagCount(); ++i) { NBTTagCompound compoundd = list.getCompoundTagAt(i); @@ -553,8 +554,8 @@ public class NBTTags { return scripts; } - public static List GetScript(NBTTagCompound compound, IScriptHandler handler) { - ArrayList scripts = new ArrayList<>(); + public static List GetScript(NBTTagCompound compound, IScriptHandler handler) { + ArrayList scripts = new ArrayList<>(); for (int i = 0; i < compound.getInteger("TotalScripts"); ++i) { NBTTagCompound containerCompound = compound.getCompoundTag("Tab" + i); @@ -566,12 +567,9 @@ public class NBTTags { return scripts; } - public static NBTTagList NBTScript(List scripts) { + public static NBTTagList NBTScript(List scripts) { NBTTagList list = new NBTTagList(); - Iterator var2 = scripts.iterator(); - - while (var2.hasNext()) { - ScriptContainer script = (ScriptContainer) var2.next(); + for (IScriptUnit script : scripts) { NBTTagCompound compound = new NBTTagCompound(); script.writeToNBT(compound); list.appendTag(compound); diff --git a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java index 8babf8936..2ecdb518e 100644 --- a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java +++ b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java @@ -28,6 +28,7 @@ import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptBlockHandler; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.entity.data.DataTimers; import noppes.npcs.scripted.BlockScriptedWrapper; import noppes.npcs.util.ValueUtil; @@ -40,7 +41,7 @@ import java.util.Map.Entry; import java.util.TreeMap; public class TileScripted extends TileEntity implements IScriptBlockHandler { - public List scripts = new ArrayList<>(); + public List scripts = new ArrayList<>(); public Map tempData = new HashMap<>(); @@ -367,8 +368,10 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler { EventHooks.onScriptBlockInit(this); } - for (ScriptContainer script : scripts) { - script.run(type, event); + for (IScriptUnit script : scripts) { + if (script instanceof ScriptContainer) { + ((ScriptContainer) script).run(type, event); + } } } @@ -408,12 +411,12 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler { } @Override - public void setScripts(List list) { + public void setScripts(List list) { scripts = list; } @Override - public List getScripts() { + public List getScripts() { return scripts; } @@ -421,9 +424,9 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler { public Map getConsoleText() { Map map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : getScripts()) { + for (IScriptUnit script : getScripts()) { tab++; - for (Entry entry : script.console.entrySet()) { + for (Entry entry : script.getConsole().entrySet()) { map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } @@ -432,8 +435,8 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler { @Override public void clearConsole() { - for (ScriptContainer script : getScripts()) { - script.console.clear(); + for (IScriptUnit script : getScripts()) { + script.clearConsole(); } } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java b/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java index 027f51a60..8b72bb145 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java @@ -7,6 +7,7 @@ import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.DataScript; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.entity.EntityNPCInterface; import java.util.ArrayList; @@ -49,9 +50,9 @@ public class GuiNPCEventScripts extends GuiScriptInterface { public void save() { if (loaded) { super.save(); - List containers = this.script.getScripts(); + List containers = this.script.getScripts(); for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); + IScriptUnit container = containers.get(i); EventScriptPacket.Save(i, containers.size(), container.writeToNBT(new NBTTagCompound())); } NBTTagCompound scriptData = new NBTTagCompound(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java index cef9096bd..27e2f8433 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java @@ -7,6 +7,7 @@ import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.GlobalNPCDataScript; +import noppes.npcs.controllers.data.IScriptUnit; import java.util.ArrayList; import java.util.List; @@ -47,9 +48,9 @@ public class GuiScriptAllNPCs extends GuiScriptInterface { public void save() { if (loaded) { super.save(); - List containers = this.script.getScripts(); + List containers = this.script.getScripts(); for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); + IScriptUnit container = containers.get(i); GlobalNPCScriptPacket.Save(i, containers.size(), container.writeToNBT(new NBTTagCompound())); } NBTTagCompound scriptData = new NBTTagCompound(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java index 01a179d54..d4aa8ade7 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java @@ -17,6 +17,7 @@ import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.ForgeDataScript; +import noppes.npcs.controllers.data.IScriptUnit; import org.apache.commons.lang3.StringUtils; import java.io.IOException; @@ -102,9 +103,9 @@ public class GuiScriptForge extends GuiScriptInterface { public void save() { if (loaded) { super.save(); - List containers = this.script.getScripts(); + List containers = this.script.getScripts(); for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); + IScriptUnit container = containers.get(i); ForgeScriptPacket.Save(i, containers.size(), container.writeToNBT(new NBTTagCompound())); } NBTTagCompound scriptData = new NBTTagCompound(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 1df897ecc..2e0173a87 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -25,6 +25,7 @@ import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.ForgeDataScript; import noppes.npcs.controllers.data.IScriptHandler; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.scripted.item.ScriptCustomItem; import org.lwjgl.opengl.Display; import org.lwjgl.opengl.GL11; @@ -159,7 +160,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb * Handles both normal and fullscreen modes. */ private void initScriptEditorTab(int yoffset) { - ScriptContainer container = getCurrentContainer(); + IScriptUnit container = getCurrentContainer(); // ==================== CALCULATE VIEWPORT BOUNDS ==================== int editorX, editorY, editorWidth, editorHeight; @@ -207,13 +208,13 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb GuiScriptTextArea activeArea = getActiveScriptArea(); if (activeArea == null) { activeArea = new GuiScriptTextArea(this, 2, editorX, editorY, editorWidth, editorHeight, - container == null ? "" : container.script); + container == null ? "" : container.getScript()); activeArea.setListener(this); this.closeOnEsc(activeArea::closeOnEsc); textAreas.put(idx, activeArea); } else { activeArea.init(editorX, editorY, editorWidth, editorHeight, - container == null ? "" : container.script); + container == null ? "" : container.getScript()); } // Setup fullscreen key binding @@ -244,7 +245,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb scroll.guiLeft = left1; scroll.guiTop = this.guiTop + 88 + yoffset; if (container != null) { - scroll.setList(container.scripts); + scroll.setList(container.getExternalScripts()); } this.addScroll(scroll); } @@ -420,7 +421,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb * Get the current script container. * Override in subclasses with different container access patterns. */ - protected ScriptContainer getCurrentContainer() { + protected IScriptUnit getCurrentContainer() { int idx = getActiveScriptIndex(); if (idx >= 0 && idx < this.handler.getScripts().size()) return this.handler.getScripts().get(idx); @@ -437,7 +438,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb return super.getTextField(id); } - public ScriptContainer getFirst() { + public IScriptUnit getFirst() { if (this.handler.getScripts().isEmpty()) return null; return this.handler.getScripts().get(0); @@ -530,7 +531,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb protected void setScript() { if (this.activeTab > 0 || useScrollTabs) { - ScriptContainer container = getCurrentContainer(); + IScriptUnit container = getCurrentContainer(); if (container == null) { container = new ScriptContainer(this.handler); if (singleContainer) @@ -542,7 +543,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb String text = (this.getTextField(2)).getText(); text = text.replace("\r\n", "\n"); text = text.replace("\r", "\n"); - container.script = text; + container.setScript(text); } } @@ -629,7 +630,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb /** * Set the handler's container. Override if handler is not IScriptHandler. */ - protected void setHandlerContainer(ScriptContainer container) { + protected void setHandlerContainer(IScriptUnit container) { // Default implementation - subclasses may need to cast and set differently // e.g., ((LinkedItemScript) handler).container = container; } @@ -642,9 +643,9 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb if (loaded) { this.setScript(); - List containers = this.handler.getScripts(); + List containers = this.handler.getScripts(); for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); + IScriptUnit container = containers.get(i); sendSavePacket(i, containers.size(), container.writeToNBT(new NBTTagCompound())); } @@ -673,9 +674,9 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } public void textUpdate(String text) { - ScriptContainer container = getCurrentContainer(); + IScriptUnit container = getCurrentContainer(); if (container != null) { - container.script = text; + container.setScript(text); } } @@ -684,9 +685,9 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb @Override //NEVER USED public void saveText(String text) { - ScriptContainer container = getCurrentContainer(); + IScriptUnit container = getCurrentContainer(); if (container != null) - container.script = text; + container.setScript(text); initGui(); } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java index e0dfc8366..2befb8d74 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java @@ -6,7 +6,8 @@ import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.NBTTags; import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.controllers.ScriptContainer; -import noppes.npcs.controllers.ScriptHookController; +import noppes.npcs.controllers.data.EffectScript; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.controllers.data.PlayerDataScript; import java.util.ArrayList; @@ -49,9 +50,9 @@ public class GuiScriptPlayers extends GuiScriptInterface { public void save() { if (loaded) { super.save(); - List containers = this.script.getScripts(); + List containers = this.script.getScripts(); for (int i = 0; i < containers.size(); i++) { - ScriptContainer container = containers.get(i); + IScriptUnit container = containers.get(i); PlayerScriptPacket.Save(i, containers.size(), container.writeToNBT(new NBTTagCompound())); } NBTTagCompound scriptData = new NBTTagCompound(); diff --git a/src/main/java/noppes/npcs/controllers/ScriptContainer.java b/src/main/java/noppes/npcs/controllers/ScriptContainer.java index 3ea46b6a7..70e29df25 100644 --- a/src/main/java/noppes/npcs/controllers/ScriptContainer.java +++ b/src/main/java/noppes/npcs/controllers/ScriptContainer.java @@ -7,6 +7,7 @@ import noppes.npcs.NBTTags; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.data.IScriptHandler; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.scripted.NpcAPI; import javax.script.Compilable; @@ -24,7 +25,7 @@ import java.util.Map; import java.util.Objects; import java.util.TreeMap; -public class ScriptContainer { +public class ScriptContainer implements IScriptUnit { private static final String lock = "lock"; public static ScriptContainer Current; private static String CurrentType; @@ -251,6 +252,7 @@ public class ScriptContainer { return evaluated && !errored; } + @Override public boolean hasCode() { if (!scripts.isEmpty()) return true; @@ -267,4 +269,73 @@ public class ScriptContainer { this.evaluated = false; } } + + // ==================== IScriptUnit IMPLEMENTATION ==================== + + @Override + public String getScript() { + return this.script; + } + + @Override + public void setScript(String script) { + this.script = script; + this.evaluated = false; + } + + @Override + public List getExternalScripts() { + return this.scripts; + } + + @Override + public void setExternalScripts(List scripts) { + this.scripts = scripts; + this.evaluated = false; + } + + @Override + public TreeMap getConsole() { + return this.console; + } + + @Override + public void clearConsole() { + this.console.clear(); + } + + @Override + public String getLanguage() { + // If a specific language is set for this container, use it + // Otherwise fall back to the handler's language + if (currentScriptLanguage != null) { + return currentScriptLanguage; + } + return handler != null ? handler.getLanguage() : "ECMAScript"; + } + + @Override + public void setLanguage(String language) { + if (!Objects.equals(this.currentScriptLanguage, language)) { + this.currentScriptLanguage = language; + this.evaluated = false; + } + } + + @Override + public String generateHookStub(String hookName, Object hookData) { + // ECMAScript function template + return "function " + hookName + "(event) {\n \n}\n"; + } + + @Override + public boolean hasErrored() { + return this.errored; + } + + @Override + public void setErrored(boolean errored) { + this.errored = errored; + } } + diff --git a/src/main/java/noppes/npcs/controllers/data/DataScript.java b/src/main/java/noppes/npcs/controllers/data/DataScript.java index bf4327d38..45ba9a966 100644 --- a/src/main/java/noppes/npcs/controllers/data/DataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/DataScript.java @@ -36,7 +36,7 @@ import java.util.Map; import java.util.TreeMap; public class DataScript implements INpcScriptHandler { - public List eventScripts = new ArrayList<>(); + public List eventScripts = new ArrayList<>(); private HashMap scripts = new HashMap<>(); private final static EntityType entities = new EntityType(); @@ -146,14 +146,16 @@ public class DataScript implements INpcScriptHandler { if (!hasInited && !npc.isRemote() && type != EnumScriptType.INIT) { hasInited = true; - for (ScriptContainer scriptContainer : this.eventScripts) { - scriptContainer.errored = false; + for (IScriptUnit scriptUnit : this.eventScripts) { + scriptUnit.setErrored(false); } EventHooks.onNPCInit(this.npc); } - for (ScriptContainer script : this.eventScripts) { - script.run(type, event); + for (IScriptUnit script : this.eventScripts) { + if (script instanceof ScriptContainer) { + ((ScriptContainer) script).run(type, event); + } } ScriptContainer script = scripts.get(type); @@ -224,10 +226,10 @@ public class DataScript implements INpcScriptHandler { public Map getConsoleText() { TreeMap map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : this.getScripts()) { + for (IScriptUnit script : this.getScripts()) { ++tab; - for (Map.Entry longStringEntry : script.console.entrySet()) { + for (Map.Entry longStringEntry : script.getConsole().entrySet()) { map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + longStringEntry.getValue()); } } @@ -235,8 +237,8 @@ public class DataScript implements INpcScriptHandler { } public void clearConsole() { - for (ScriptContainer script : this.getScripts()) { - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } @@ -274,11 +276,11 @@ public class DataScript implements INpcScriptHandler { this.scriptLanguage = lang; } - public void setScripts(List list) { + public void setScripts(List list) { this.eventScripts = list; } - public List getScripts() { + public List getScripts() { return this.eventScripts; } diff --git a/src/main/java/noppes/npcs/controllers/data/EffectScript.java b/src/main/java/noppes/npcs/controllers/data/EffectScript.java index bd2b75dae..497b46421 100644 --- a/src/main/java/noppes/npcs/controllers/data/EffectScript.java +++ b/src/main/java/noppes/npcs/controllers/data/EffectScript.java @@ -15,13 +15,12 @@ import noppes.npcs.scripted.event.player.PlayerEvent; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; public class EffectScript implements INpcScriptHandler { - public ScriptContainer container; + public IScriptUnit container; public String scriptLanguage = "ECMAScript"; public boolean enabled = false; @@ -64,7 +63,8 @@ public class EffectScript implements INpcScriptHandler { if (!this.isEnabled()) { return; } - container.run(s, event); + if (container instanceof ScriptContainer) + ((ScriptContainer) container).run(s, event); } @Override @@ -93,7 +93,7 @@ public class EffectScript implements INpcScriptHandler { } @Override - public void setScripts(List list) { + public void setScripts(List list) { if (list == null || list.isEmpty()) { container = null; return; @@ -102,7 +102,7 @@ public class EffectScript implements INpcScriptHandler { } @Override - public List getScripts() { + public List getScripts() { if (container == null) return new ArrayList<>(); return Collections.singletonList(container); @@ -115,31 +115,21 @@ public class EffectScript implements INpcScriptHandler { @Override public Map getConsoleText() { - TreeMap map = new TreeMap(); + TreeMap map = new TreeMap<>(); int tab = 0; - Iterator var3 = this.getScripts().iterator(); - - while (var3.hasNext()) { - ScriptContainer script = (ScriptContainer) var3.next(); + for (IScriptUnit script : this.getScripts()) { ++tab; - Iterator var5 = script.console.entrySet().iterator(); - - while (var5.hasNext()) { - Map.Entry longStringEntry = (Map.Entry) var5.next(); - map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + (String) longStringEntry.getValue()); + for (Map.Entry entry : script.getConsole().entrySet()) { + map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } - return map; } @Override public void clearConsole() { - Iterator var1 = this.getScripts().iterator(); - - while (var1.hasNext()) { - ScriptContainer script = (ScriptContainer) var1.next(); - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } @@ -180,4 +170,4 @@ public class EffectScript implements INpcScriptHandler { this.function = functionName; } } -} +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java index dde123aae..d38342f0e 100644 --- a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java @@ -16,7 +16,7 @@ import java.util.Map.Entry; import java.util.TreeMap; public class ForgeDataScript implements INpcScriptHandler { - private List scripts = new ArrayList(); + private List scripts = new ArrayList<>(); private String scriptLanguage = "ECMAScript"; public long lastInited = -1L; private long lastForgeUpdate = -1L; @@ -26,14 +26,14 @@ public class ForgeDataScript implements INpcScriptHandler { } public void clear() { - this.scripts = new ArrayList(); + this.scripts = new ArrayList<>(); } public void readFromNBT(NBTTagCompound compound) { if (compound.hasKey("Scripts")) { - this.scripts = NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this); + this.scripts = new ArrayList<>(NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this)); } else { - this.scripts = NBTTags.GetScript(compound, this); + this.scripts = new ArrayList<>(NBTTags.GetScript(compound, this)); } this.scriptLanguage = compound.getString("ScriptLanguage"); if (!ScriptController.Instance.languages.containsKey(scriptLanguage)) { @@ -67,8 +67,9 @@ public class ForgeDataScript implements INpcScriptHandler { this.lastInited = ScriptController.Instance.lastLoaded; this.lastForgeUpdate = ScriptController.Instance.lastForgeUpdate; - for (ScriptContainer script : this.scripts) { - script.errored = false; + for (IScriptUnit script : this.scripts) { + if (script instanceof ScriptContainer) + ((ScriptContainer) script).errored = false; } if (!type.equals("init")) { @@ -76,11 +77,15 @@ public class ForgeDataScript implements INpcScriptHandler { } } - for (ScriptContainer script : this.scripts) { - if (script == null || script.errored || !script.hasCode()) + for (IScriptUnit script : this.scripts) { + if (script == null || !script.hasCode()) continue; - - script.run(type, event); + if (script instanceof ScriptContainer) { + ScriptContainer container = (ScriptContainer) script; + if (container.errored) + continue; + container.run(type, event); + } } } } @@ -109,11 +114,11 @@ public class ForgeDataScript implements INpcScriptHandler { this.scriptLanguage = lang; } - public void setScripts(List list) { + public void setScripts(List list) { this.scripts = list; } - public List getScripts() { + public List getScripts() { return this.scripts; } @@ -124,19 +129,18 @@ public class ForgeDataScript implements INpcScriptHandler { public Map getConsoleText() { TreeMap map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : this.getScripts()) { + for (IScriptUnit script : this.getScripts()) { ++tab; - - for (Entry longStringEntry : script.console.entrySet()) { - map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + longStringEntry.getValue()); + for (Entry entry : script.getConsole().entrySet()) { + map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } return map; } public void clearConsole() { - for (ScriptContainer script : this.getScripts()) { - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java index 335256e0f..f21818136 100644 --- a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java @@ -27,7 +27,7 @@ import java.util.OptionalLong; import java.util.TreeMap; public class GlobalNPCDataScript implements INpcScriptHandler { - public List scripts = new ArrayList(); + public List scripts = new ArrayList<>(); public String scriptLanguage = "ECMAScript"; private EntityNPCInterface npc; private ICustomNpc npcAPI; @@ -42,14 +42,14 @@ public class GlobalNPCDataScript implements INpcScriptHandler { } public void clear() { - this.scripts = new ArrayList(); + this.scripts = new ArrayList<>(); } public void readFromNBT(NBTTagCompound compound) { if (compound.hasKey("Scripts")) { - this.scripts = NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this); + this.scripts = new ArrayList<>(NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this)); } else { - this.scripts = NBTTags.GetScript(compound, this); + this.scripts = new ArrayList<>(NBTTags.GetScript(compound, this)); } this.scriptLanguage = compound.getString("ScriptLanguage"); if (!ScriptController.Instance.languages.containsKey(scriptLanguage)) { @@ -87,16 +87,21 @@ public class GlobalNPCDataScript implements INpcScriptHandler { this.lastInited = ScriptController.Instance.lastLoaded; this.lastNpcUpdate = ScriptController.Instance.lastGlobalNpcUpdate; - for (ScriptContainer script : this.scripts) { - script.errored = false; + for (IScriptUnit script : this.scripts) { + if (script instanceof ScriptContainer) + ((ScriptContainer) script).errored = false; } } - for (ScriptContainer script : this.scripts) { - if (script == null || script.errored || !script.hasCode()) + for (IScriptUnit script : this.scripts) { + if (script == null || !script.hasCode()) continue; - - script.run(hookName, event); + if (script instanceof ScriptContainer) { + ScriptContainer container = (ScriptContainer) script; + if (container.errored) + continue; + container.run(hookName, event); + } } } } @@ -121,11 +126,11 @@ public class GlobalNPCDataScript implements INpcScriptHandler { this.scriptLanguage = lang; } - public void setScripts(List list) { + public void setScripts(List list) { this.scripts = list; } - public List getScripts() { + public List getScripts() { return this.scripts; } @@ -148,19 +153,18 @@ public class GlobalNPCDataScript implements INpcScriptHandler { public Map getConsoleText() { TreeMap map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : this.getScripts()) { + for (IScriptUnit script : this.getScripts()) { ++tab; - - for (Map.Entry longStringEntry : script.console.entrySet()) { - map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + longStringEntry.getValue()); + for (Map.Entry entry : script.getConsole().entrySet()) { + map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } return map; } public void clearConsole() { - for (ScriptContainer script : this.getScripts()) { - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java b/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java index be37c86f1..d89fbc7a2 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java @@ -1,7 +1,6 @@ package noppes.npcs.controllers.data; import cpw.mods.fml.common.eventhandler.Event; -import noppes.npcs.controllers.ScriptContainer; import java.util.List; import java.util.Map; @@ -19,9 +18,9 @@ public interface IScriptHandler { void setLanguage(String language); - void setScripts(List list); + void setScripts(List list); - List getScripts(); + List getScripts(); String noticeString(); diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java new file mode 100644 index 000000000..d8d280be0 --- /dev/null +++ b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java @@ -0,0 +1,117 @@ +package noppes.npcs.controllers.data; + +import net.minecraft.nbt.NBTTagCompound; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +/** + * Common interface for script units that can be edited in a script GUI. + * Implemented by both ScriptContainer (ECMAScript) and JaninoScript (Java/Janino). + * This allows GuiScriptInterface to work with both script types uniformly. + */ +public interface IScriptUnit { + + // ==================== SCRIPT CONTENT ==================== + + /** + * Get the main script text content. + */ + String getScript(); + + /** + * Set the main script text content. + */ + void setScript(String script); + + /** + * Get the list of external script file names loaded for this unit. + */ + List getExternalScripts(); + + /** + * Set the list of external script file names to load. + */ + void setExternalScripts(List scripts); + + // ==================== CONSOLE ==================== + + /** + * Get the console output map (timestamp -> message). + */ + TreeMap getConsole(); + + /** + * Clear all console output. + */ + void clearConsole(); + + /** + * Append a message to the console. + */ + void appendConsole(String message); + + // ==================== LANGUAGE ==================== + + /** + * Get the scripting language for this unit. + * Returns "ECMAScript", "Java", etc. + */ + String getLanguage(); + + /** + * Set the scripting language for this unit. + * @param language The language name (e.g., "ECMAScript", "Java") + */ + void setLanguage(String language); + + /** + * Check if this script unit uses Janino (Java) compilation. + */ + default boolean isJanino() { + return "Java".equals(getLanguage()); + } + + // ==================== HOOK GENERATION ==================== + + /** + * Generate a stub/template for the given hook name. + * ECMAScript: function hookName(event) { } + * Janino: full Java method signature with return type + * + * @param hookName The hook name to generate a stub for + * @param hookData Optional data (e.g., Method object for Janino) + * @return The generated stub string + */ + String generateHookStub(String hookName, Object hookData); + + // ==================== NBT ==================== + + /** + * Write this script unit to NBT. + */ + NBTTagCompound writeToNBT(NBTTagCompound compound); + + /** + * Read this script unit from NBT. + */ + void readFromNBT(NBTTagCompound compound); + + // ==================== STATE ==================== + + /** + * Check if this script unit has any code (script or external scripts). + */ + boolean hasCode(); + + /** + * Check if this script unit has encountered an error during execution. + */ + boolean hasErrored(); + + /** + * Set the error state of this script unit. + */ + void setErrored(boolean errored); +} diff --git a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java index cce8df255..18df07229 100644 --- a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java +++ b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java @@ -14,13 +14,12 @@ import noppes.npcs.controllers.ScriptController; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeMap; public class LinkedItemScript implements INpcScriptHandler { - public ScriptContainer container; + public IScriptUnit container; public String scriptLanguage = "ECMAScript"; public boolean enabled = false; @@ -58,7 +57,8 @@ public class LinkedItemScript implements INpcScriptHandler { if (!this.isEnabled()) { return; } - container.run(s, event); + if (container instanceof ScriptContainer) + ((ScriptContainer) container).run(s, event); } @Override @@ -87,7 +87,7 @@ public class LinkedItemScript implements INpcScriptHandler { } @Override - public void setScripts(List list) { + public void setScripts(List list) { if (list == null || list.isEmpty()) { container = null; return; @@ -96,7 +96,7 @@ public class LinkedItemScript implements INpcScriptHandler { } @Override - public List getScripts() { + public List getScripts() { if (container == null) return new ArrayList<>(); return Collections.singletonList(container); @@ -109,31 +109,21 @@ public class LinkedItemScript implements INpcScriptHandler { @Override public Map getConsoleText() { - TreeMap map = new TreeMap(); + TreeMap map = new TreeMap<>(); int tab = 0; - Iterator var3 = this.getScripts().iterator(); - - while (var3.hasNext()) { - ScriptContainer script = (ScriptContainer) var3.next(); + for (IScriptUnit script : this.getScripts()) { ++tab; - Iterator var5 = script.console.entrySet().iterator(); - - while (var5.hasNext()) { - Map.Entry longStringEntry = (Map.Entry) var5.next(); - map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + (String) longStringEntry.getValue()); + for (Map.Entry entry : script.getConsole().entrySet()) { + map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } - return map; } @Override public void clearConsole() { - Iterator var1 = this.getScripts().iterator(); - - while (var1.hasNext()) { - ScriptContainer script = (ScriptContainer) var1.next(); - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java index a425bdcd4..5d2eee9f9 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java @@ -31,7 +31,7 @@ import java.util.OptionalLong; import java.util.TreeMap; public class PlayerDataScript implements INpcScriptHandler { - public List scripts = new ArrayList(); + public List scripts = new ArrayList<>(); public String scriptLanguage = "ECMAScript"; private EntityPlayer player; private IPlayer playerAPI; @@ -53,14 +53,14 @@ public class PlayerDataScript implements INpcScriptHandler { public void clear() { console = new TreeMap(); errored = new ArrayList(); - scripts = new ArrayList(); + scripts = new ArrayList<>(); } public void readFromNBT(NBTTagCompound compound) { if (compound.hasKey("Scripts")) { - this.scripts = NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this); + this.scripts = new ArrayList<>(NBTTags.GetScriptOld(compound.getTagList("Scripts", 10), this)); } else { - this.scripts = NBTTags.GetScript(compound, this); + this.scripts = new ArrayList<>(NBTTags.GetScript(compound, this)); } this.scriptLanguage = compound.getString("ScriptLanguage"); if (!ScriptController.Instance.languages.containsKey(scriptLanguage)) { @@ -104,10 +104,12 @@ public class PlayerDataScript implements INpcScriptHandler { errored.clear(); if (player != null) { scripts.clear(); - for (ScriptContainer script : ScriptController.Instance.playerScripts.scripts) { - ScriptContainer s = new ScriptContainer(this); - s.readFromNBT(script.writeToNBT(new NBTTagCompound())); - scripts.add(s); + for (IScriptUnit script : ScriptController.Instance.playerScripts.scripts) { + if (script instanceof ScriptContainer) { + ScriptContainer s = new ScriptContainer(this); + s.readFromNBT(((ScriptContainer) script).writeToNBT(new NBTTagCompound())); + scripts.add(s); + } } } lastPlayerUpdate = ScriptController.Instance.lastPlayerUpdate; @@ -117,26 +119,30 @@ public class PlayerDataScript implements INpcScriptHandler { } } for (int i = 0; i < scripts.size(); i++) { - ScriptContainer script = scripts.get(i); + IScriptUnit script = scripts.get(i); if (errored.contains(i)) continue; - script.run(hookName, event); - if (script.errored) { - errored.add(i); + if (script instanceof ScriptContainer) { + ScriptContainer container = (ScriptContainer) script; + container.run(hookName, event); + if (container.errored) { + errored.add(i); + } + for (Entry entry : container.console.entrySet()) { + if (!console.containsKey(entry.getKey())) + console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + entry.getValue()); + } + container.console.clear(); } - for (Entry entry : script.console.entrySet()) { - if (!console.containsKey(entry.getKey())) - console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + entry.getValue()); - } - script.console.clear(); } } else { if (ScriptController.Instance.lastLoaded > this.lastInited || ScriptController.Instance.lastPlayerUpdate > this.lastPlayerUpdate) { this.lastInited = ScriptController.Instance.lastLoaded; this.lastPlayerUpdate = ScriptController.Instance.lastPlayerUpdate; - for (ScriptContainer scriptContainer : this.scripts) { - scriptContainer.errored = false; + for (IScriptUnit script : this.scripts) { + if (script instanceof ScriptContainer) + ((ScriptContainer) script).errored = false; } if (!Objects.equals(hookName, EnumScriptType.INIT.function) && event instanceof PlayerEvent) { @@ -145,11 +151,13 @@ public class PlayerDataScript implements INpcScriptHandler { } } - for (ScriptContainer script : this.scripts) { - if (script == null || script.errored || !script.hasCode()) + for (IScriptUnit script : this.scripts) { + if (script == null || script.hasErrored()|| !script.hasCode()) continue; - - script.run(hookName, event); + if (script instanceof ScriptContainer) { + ScriptContainer container = (ScriptContainer) script; + container.run(hookName, event); + } } } } @@ -175,11 +183,11 @@ public class PlayerDataScript implements INpcScriptHandler { this.scriptLanguage = lang; } - public void setScripts(List list) { + public void setScripts(List list) { this.scripts = list; } - public List getScripts() { + public List getScripts() { return this.scripts; } @@ -205,11 +213,10 @@ public class PlayerDataScript implements INpcScriptHandler { TreeMap map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : this.getScripts()) { + for (IScriptUnit script : this.getScripts()) { ++tab; - - for (Entry longStringEntry : script.console.entrySet()) { - map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + longStringEntry.getValue()); + for (Entry entry : script.getConsole().entrySet()) { + map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } return map; @@ -219,8 +226,8 @@ public class PlayerDataScript implements INpcScriptHandler { if (ConfigScript.IndividualPlayerScripts) console.clear(); else { - for (ScriptContainer script : this.getScripts()) { - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java index b94acfbc6..b42595cf5 100644 --- a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java +++ b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java @@ -19,7 +19,7 @@ import java.util.Map; import java.util.TreeMap; public class RecipeScript implements INpcScriptHandler { - public ScriptContainer container; + public IScriptUnit container; public String scriptLanguage = "ECMAScript"; public boolean enabled = false; @@ -54,7 +54,8 @@ public class RecipeScript implements INpcScriptHandler { public void callScript(String s, Event event) { if (!this.isEnabled()) return; - container.run(s, event); + if (container instanceof ScriptContainer) + ((ScriptContainer) container).run(s, event); } @Override @@ -83,7 +84,7 @@ public class RecipeScript implements INpcScriptHandler { } @Override - public void setScripts(List list) { + public void setScripts(List list) { if (list == null || list.isEmpty()) { container = null; return; @@ -92,7 +93,7 @@ public class RecipeScript implements INpcScriptHandler { } @Override - public List getScripts() { + public List getScripts() { if (container == null) return new ArrayList<>(); return Collections.singletonList(container); @@ -107,9 +108,9 @@ public class RecipeScript implements INpcScriptHandler { public Map getConsoleText() { TreeMap map = new TreeMap<>(); int tab = 0; - for (ScriptContainer script : this.getScripts()) { + for (IScriptUnit script : this.getScripts()) { ++tab; - for (Map.Entry entry : script.console.entrySet()) { + for (Map.Entry entry : script.getConsole().entrySet()) { map.put(entry.getKey(), " tab " + tab + ":\n" + entry.getValue()); } } @@ -118,8 +119,8 @@ public class RecipeScript implements INpcScriptHandler { @Override public void clearConsole() { - for (ScriptContainer script : this.getScripts()) { - script.console.clear(); + for (IScriptUnit script : this.getScripts()) { + script.clearConsole(); } } @@ -156,4 +157,4 @@ public class RecipeScript implements INpcScriptHandler { this.function = functionName; } } -} +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/janino/JaninoScript.java b/src/main/java/noppes/npcs/janino/JaninoScript.java index f836e97cf..5fb02a46e 100644 --- a/src/main/java/noppes/npcs/janino/JaninoScript.java +++ b/src/main/java/noppes/npcs/janino/JaninoScript.java @@ -8,16 +8,21 @@ import noppes.npcs.CustomNpcs; import noppes.npcs.NBTTags; import noppes.npcs.config.ConfigScript; import noppes.npcs.controllers.ScriptController; +import noppes.npcs.controllers.data.IScriptUnit; import org.codehaus.commons.compiler.InternalCompilerException; import org.codehaus.commons.compiler.Sandbox; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.security.*; import java.util.*; import java.util.function.Consumer; import java.util.function.Function; +import java.util.stream.Collectors; -public abstract class JaninoScript { +public abstract class JaninoScript implements IScriptUnit { public boolean enabled; + public boolean errored = false; private String language = "Java"; public TreeMap console = new TreeMap(); @@ -184,18 +189,132 @@ public abstract class JaninoScript { sb.append(code).append("\n"); } } + + // ==================== IScriptUnit IMPLEMENTATION ==================== + @Override + public String getScript() { + return this.script; + } + + @Override public void setScript(String script) { this.script = script; this.evaluated = false; } + + @Override + public List getExternalScripts() { + return this.externalScripts; + } + @Override public void setExternalScripts(List externalScripts) { this.externalScripts = externalScripts; this.evaluated = false; } + + @Override + public TreeMap getConsole() { + return this.console; + } + + @Override + public void clearConsole() { + console.clear(); + } + + @Override + public void appendConsole(String message) { + if (message != null && !message.isEmpty()) { + long time = System.currentTimeMillis(); + if (this.console.containsKey(time)) { + message = (String) this.console.get(time) + "\n" + message; + } + + this.console.put(time, message); + + while (this.console.size() > 40) { + this.console.remove(this.console.firstKey()); + } + } + } + + @Override + public String getLanguage() { + return this.language; + } + + @Override + public void setLanguage(String language) { + // JaninoScript is always Java, ignore attempts to change + // This method exists for IScriptUnit interface compatibility + } + + @Override + public boolean hasCode() { + if (!externalScripts.isEmpty()) + return true; + return script != null && !script.isEmpty(); + } + + @Override + public String generateHookStub(String hookName, Object hookData) { + // If hookData is a Method, generate full Java method stub + if (hookData instanceof Method) { + return generateMethodStub((Method) hookData); + } + // Fallback for simple hook names - generate basic override + return String.format("@Override\npublic void %s() {\n \n}\n", hookName); + } + + /** + * Generates a stub string for a given Method. + */ + public static String generateMethodStub(Method method) { + String mods = Modifier.toString(method.getModifiers()); + // Remove 'abstract' from modifiers for implementation + mods = mods.replace("abstract ", "").replace("abstract", "").trim(); + if (!mods.isEmpty()) + mods += " "; + + String returnTypeStr = method.getReturnType().getSimpleName(); + String name = method.getName(); + + Map typeCount = new HashMap<>(); + String params = Arrays.stream(method.getParameters()) + .map(p -> { + String typeName = p.getType().getSimpleName(); + String baseName = Character.toLowerCase(typeName.charAt(0)) + typeName.substring(1); + + int count = typeCount.getOrDefault(baseName, 0) + 1; + typeCount.put(baseName, count); + + String paramName = count == 1 ? baseName : baseName + (count - 1); + return typeName + " " + paramName; + }) + .collect(Collectors.joining(", ")); + + String body; + Class returnType = method.getReturnType(); + if (returnType == void.class) + body = ""; + else if (returnType.isPrimitive()) { + if (returnType == boolean.class) + body = " return false;"; + else if (returnType == char.class) + body = " return '\\0';"; + else + body = " return 0;"; + } else { + body = " return null;"; + } + + return String.format("@Override\n%s%s %s(%s) {\n%s\n}\n", mods, returnTypeStr, name, params, body); + } + @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { compound.setBoolean("enabled", enabled); compound.setTag("console", NBTTags.NBTLongStringMap(this.console)); @@ -204,12 +323,12 @@ public abstract class JaninoScript { return compound; } - public JaninoScript readFromNBT(NBTTagCompound compound) { + @Override + public void readFromNBT(NBTTagCompound compound) { this.enabled = compound.getBoolean("enabled"); this.console = NBTTags.GetLongStringMap(compound.getTagList("console", 10)); setExternalScripts(NBTTags.getStringList(compound.getTagList("externalScripts", 10))); - setScript(compound.getString("script")); //after everything else is read - return this; + setScript(compound.getString("script")); } public boolean isEnabled() { @@ -233,25 +352,6 @@ public abstract class JaninoScript { } } - public String getLanguage() { - return this.language; - } - - public void appendConsole(String message) { - if (message != null && !message.isEmpty()) { - long time = System.currentTimeMillis(); - if (this.console.containsKey(time)) { - message = (String) this.console.get(time) + "\n" + message; - } - - this.console.put(time, message); - - while (this.console.size() > 40) { - this.console.remove(this.console.firstKey()); - } - } - } - public Map getConsoleText() { TreeMap map = new TreeMap(); int tab = 0; @@ -264,13 +364,16 @@ public abstract class JaninoScript { map.put(longStringEntry.getKey(), " tab " + tab + ":\n" + (String) longStringEntry.getValue()); } - return map; } - - public void clearConsole() { - console.clear(); + + @Override + public boolean hasErrored() { + return this.errored; } -} - - + + @Override + public void setErrored(boolean errored) { + this.errored = errored; + } +} \ No newline at end of file diff --git a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java index 6e85e1555..e03995e16 100644 --- a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java +++ b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java @@ -7,6 +7,7 @@ import noppes.npcs.EventHooks; import noppes.npcs.NBTTags; import noppes.npcs.api.item.IItemCustom; import noppes.npcs.constants.EnumScriptType; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.INpcScriptHandler; @@ -19,7 +20,7 @@ import java.util.Objects; import java.util.TreeMap; public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCustom, INpcScriptHandler { - public List scripts = new ArrayList(); + public List scripts = new ArrayList(); public List errored = new ArrayList(); public String scriptLanguage = "ECMAScript"; public boolean enabled = false; @@ -95,14 +96,16 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus } for (int i = 0; i < this.scripts.size(); i++) { - ScriptContainer script = this.scripts.get(i); + IScriptUnit script = this.scripts.get(i); if (!this.errored.contains(i)) { - if (script == null || script.errored || !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - script.run(hookName, event); + if (script instanceof ScriptContainer) { + ((ScriptContainer) script).run(hookName, event); + } - if (script.errored) { + if (script.hasErrored()) { this.errored.add(i); } } @@ -129,11 +132,11 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus this.scriptLanguage = lang; } - public void setScripts(List list) { + public void setScripts(List list) { this.scripts = list; } - public List getScripts() { + public List getScripts() { return this.scripts; } From cd92c340c72cc8a8097ecf0e00172ab7e3e57c12 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 18:14:38 +0200 Subject: [PATCH 04/19] resolved merge conflicts with dev --- .../client/gui/script/GuiScriptBlock.java | 2 +- .../client/gui/script/GuiScriptEffect.java | 3 ++ .../client/gui/script/GuiScriptInterface.java | 49 +++++++++++++++++++ .../npcs/client/gui/script/GuiScriptItem.java | 7 +-- .../gui/script/GuiScriptLinkedItem.java | 3 ++ .../client/gui/script/GuiScriptRecipe.java | 3 ++ .../npcs/controllers/data/IScriptHandler.java | 19 +++++++ .../java/noppes/npcs/scripted/NpcAPI.java | 17 +------ 8 files changed, 81 insertions(+), 22 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java index a97efa90f..c95c2c443 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java @@ -4,11 +4,11 @@ import kamkeel.npcs.network.packets.request.script.BlockScriptPacket; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.blocks.tiles.TileScripted; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptHookController; import java.util.ArrayList; - public class GuiScriptBlock extends GuiScriptInterface { private final TileScripted tileScripted; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java index 1f51339f1..bd5f59b1e 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java @@ -2,6 +2,7 @@ package noppes.npcs.client.gui.script; import kamkeel.npcs.network.packets.request.script.EffectScriptPacket; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.client.gui.global.GuiNPCManageEffects; import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; @@ -9,6 +10,8 @@ import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.CustomEffect; import noppes.npcs.controllers.data.EffectScript; +import java.util.ArrayList; + public class GuiScriptEffect extends GuiScriptInterface { public final CustomEffect effect; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 2e0173a87..5f180e578 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -216,6 +216,14 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb activeArea.init(editorX, editorY, editorWidth, editorHeight, container == null ? "" : container.getScript()); } + + // Set the scripting language for proper syntax highlighting + // Use the container's language if available, otherwise fall back to handler's language + String language = (container != null) ? container.getLanguage() : this.handler.getLanguage(); + activeArea.setLanguage(language); + + // Set the script context for context-aware hook autocomplete + activeArea.setScriptContext(getScriptContext()); // Setup fullscreen key binding GuiScriptTextArea.KEYS.FULLSCREEN.setTask(e -> { @@ -238,6 +246,13 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb this.addButton(new GuiNpcButton(101, left1 + 61, this.guiTop + yoffset, 60, 20, "gui.paste")); this.addButton(new GuiNpcButton(100, left1, this.guiTop + 21 + yoffset, 60, 20, "gui.copy")); this.addButton(new GuiNpcButton(105, left1 + 61, this.guiTop + 21 + yoffset, 60, 20, "gui.remove")); + + // Language toggle button (only if handler supports Janino) + if (handler.supportsJanino() && container != null) { + String langLabel = container.isJanino() ? "Java" : "ECMAScript"; + this.addButton(new GuiNpcButton(113, left1, this.guiTop + 42 + yoffset, 121, 20, langLabel)); + } + this.addButton(new GuiNpcButton(107, left1, this.guiTop + 66 + yoffset, 80, 20, "script.loadscript")); GuiCustomScroll scroll = (new GuiCustomScroll(this, 0)).setUnselectable(); @@ -527,6 +542,40 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb this.setSubGui(new EventGuiScriptList((List) this.languages.get(this.handler.getLanguage()), container)); } + + // Language toggle button - switch between ECMAScript and Java + if (guibutton.id == 113) { + int idx = getActiveScriptIndex(); + if (idx >= 0 && idx < handler.getScripts().size()) { + IScriptUnit currentUnit = handler.getScripts().get(idx); + IScriptUnit newUnit; + + if (currentUnit.isJanino()) { + // Switch from Java to ECMAScript + newUnit = new ScriptContainer(handler); + newUnit.setScript(currentUnit.getScript()); + newUnit.setExternalScripts(new ArrayList<>(currentUnit.getExternalScripts())); + } else { + // Switch from ECMAScript to Java + newUnit = handler.createJaninoScriptUnit(); + if (newUnit != null) { + newUnit.setScript(currentUnit.getScript()); + newUnit.setExternalScripts(new ArrayList<>(currentUnit.getExternalScripts())); + } else { + return; // Handler doesn't support Janino + } + } + + // Replace the script unit in the list + handler.getScripts().set(idx, newUnit); + + // Clear the cached text area so it recreates with new language + textAreas.remove(idx); + + // Reinitialize the GUI + initGui(); + } + } } protected void setScript() { diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java index 8b2a423cf..cb5b807f2 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java @@ -7,14 +7,11 @@ import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.CustomItems; import noppes.npcs.NBTTags; import noppes.npcs.api.handler.IScriptHookHandler; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.scripted.item.ScriptCustomItem; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; +import java.util.*; public class GuiScriptItem extends GuiScriptInterface { private ScriptCustomItem item; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java index 306b62a91..d00c7b2c3 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java @@ -2,6 +2,7 @@ package noppes.npcs.client.gui.script; import kamkeel.npcs.network.packets.request.script.item.LinkedItemScriptPacket; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.client.gui.global.GuiNPCManageLinked; import noppes.npcs.constants.EnumScriptType; import noppes.npcs.constants.ScriptContext; @@ -10,6 +11,8 @@ import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.LinkedItem; import noppes.npcs.controllers.data.LinkedItemScript; +import java.util.ArrayList; + public class GuiScriptLinkedItem extends GuiScriptInterface { public final LinkedItem linkedItem; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java index d401bc274..262151d5c 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java @@ -2,6 +2,7 @@ package noppes.npcs.client.gui.script; import kamkeel.npcs.network.packets.request.script.RecipeScriptPacket; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.client.gui.global.GuiNpcManageRecipes; import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; @@ -10,6 +11,8 @@ import noppes.npcs.controllers.data.RecipeAnvil; import noppes.npcs.controllers.data.RecipeCarpentry; import noppes.npcs.controllers.data.RecipeScript; +import java.util.ArrayList; + public class GuiScriptRecipe extends GuiScriptInterface { public final int recipeId; diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java b/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java index d89fbc7a2..2aa9c1db5 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java @@ -27,4 +27,23 @@ public interface IScriptHandler { Map getConsoleText(); void clearConsole(); + + /** + * Create a new Janino (Java) script unit for this handler. + * Handlers that don't support Janino scripts should return null. + * + * @return A new JaninoScript instance, or null if not supported + */ + default IScriptUnit createJaninoScriptUnit() { + return null; // Default: Janino not supported + } + + /** + * Check if this handler supports Janino (Java) scripts. + * + * @return true if createJaninoScriptUnit() can create valid Janino scripts + */ + default boolean supportsJanino() { + return createJaninoScriptUnit() != null; + } } diff --git a/src/main/java/noppes/npcs/scripted/NpcAPI.java b/src/main/java/noppes/npcs/scripted/NpcAPI.java index 26a0eb89a..3d71e0023 100644 --- a/src/main/java/noppes/npcs/scripted/NpcAPI.java +++ b/src/main/java/noppes/npcs/scripted/NpcAPI.java @@ -59,22 +59,7 @@ import noppes.npcs.api.entity.ICustomNpc; import noppes.npcs.api.entity.IEntity; import noppes.npcs.api.entity.IPlayer; import noppes.npcs.api.gui.ICustomGui; -import noppes.npcs.api.handler.IActionManager; -import noppes.npcs.api.handler.IAbilityHandler; -import noppes.npcs.api.handler.IAnimationHandler; -import noppes.npcs.api.handler.IAttributeHandler; -import noppes.npcs.api.handler.ICloneHandler; -import noppes.npcs.api.handler.ICustomEffectHandler; -import noppes.npcs.api.handler.IDialogHandler; -import noppes.npcs.api.handler.IFactionHandler; -import noppes.npcs.api.handler.IMagicHandler; -import noppes.npcs.api.handler.INaturalSpawnsHandler; -import noppes.npcs.api.handler.IPartyHandler; -import noppes.npcs.api.handler.IProfileHandler; -import noppes.npcs.api.handler.IQuestHandler; -import noppes.npcs.api.handler.IRecipeHandler; -import noppes.npcs.api.handler.IScriptHookHandler; -import noppes.npcs.api.handler.ITransportHandler; +import noppes.npcs.api.handler.*; import noppes.npcs.api.handler.data.IAnimation; import noppes.npcs.api.handler.data.IFrame; import noppes.npcs.api.handler.data.IFramePart; From 71dba152704128fc6d55484801f7c0eadcdd4297 Mon Sep 17 00:00:00 2001 From: Kam Date: Fri, 9 Jan 2026 22:59:13 -0500 Subject: [PATCH 05/19] Add Script Context and better parsing for d.ts handling --- .gitignore | 4 + .../noppes/npcs/client/gui/GuiScript.java | 7 +- .../client/gui/script/GuiScriptBlock.java | 6 +- .../client/gui/script/GuiScriptInterface.java | 94 +------- .../npcs/client/gui/script/GuiScriptItem.java | 7 +- .../client/gui/script/GuiScriptPlayers.java | 8 +- .../client/gui/util/GuiScriptTextArea.java | 22 ++ .../noppes/npcs/constants/ScriptContext.java | 201 ++++++++++++++++++ 8 files changed, 253 insertions(+), 96 deletions(-) create mode 100644 src/main/java/noppes/npcs/constants/ScriptContext.java diff --git a/.gitignore b/.gitignore index 23d9047f1..ed907b3d2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,13 @@ /out/ /build/ /eclipse/ +/gradle-plugins/ .classpath .project /bin/ /config/ +/copilot/ +/buildSrc/build/ /crash-reports/ /logs/ options.txt @@ -39,3 +42,4 @@ addon.late.local.gradle.kts layout.json out run +src/main/resources/assets/customnpcs/api \ No newline at end of file diff --git a/src/main/java/noppes/npcs/client/gui/GuiScript.java b/src/main/java/noppes/npcs/client/gui/GuiScript.java index a8017222d..4349b1ef6 100644 --- a/src/main/java/noppes/npcs/client/gui/GuiScript.java +++ b/src/main/java/noppes/npcs/client/gui/GuiScript.java @@ -13,6 +13,7 @@ import noppes.npcs.client.NoppesUtil; import noppes.npcs.client.gui.script.GuiNPCEventScripts; import noppes.npcs.client.gui.script.GuiScriptInterface; import noppes.npcs.client.gui.util.*; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.DataScript; @@ -166,8 +167,10 @@ public class GuiScript extends GuiScriptInterface { int scrollbarOffset = activeArea.hasVerticalScrollbar() ? -8 : -2; fullscreenButton.initGui(editorX + editorWidth, editorY, scrollbarOffset); - // ==================== RIGHT PANEL BUTTONS (hidden in fullscreen) ==================== - if (!isFullscreen) { + // Set language and script context for proper syntax highlighting and autocomplete + activeArea.setLanguage(script.getLanguage()); + activeArea.setScriptContext(ScriptContext.NPC); + addButton(new GuiNpcButton(102, guiLeft + 315, guiTop + 4, 50, 20, "gui.clear")); addButton(new GuiNpcButton(101, guiLeft + 366, guiTop + 4, 50, 20, "gui.paste")); addButton(new GuiNpcButton(100, guiLeft + 315, guiTop + 25, 50, 20, "gui.copy")); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java index c95c2c443..5b9762a96 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java @@ -5,7 +5,6 @@ import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.blocks.tiles.TileScripted; import noppes.npcs.constants.ScriptContext; -import noppes.npcs.controllers.ScriptHookController; import java.util.ArrayList; @@ -25,6 +24,11 @@ public class GuiScriptBlock extends GuiScriptInterface { loaded = true; } + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.BLOCK; + } + public void save() { if (loaded) { super.save(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 5f180e578..11c326880 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -23,6 +23,7 @@ import noppes.npcs.client.gui.util.ITextChangeListener; import noppes.npcs.client.gui.util.ITextfieldListener; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.data.ForgeDataScript; import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.controllers.data.IScriptUnit; @@ -225,6 +226,9 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb // Set the script context for context-aware hook autocomplete activeArea.setScriptContext(getScriptContext()); + // Set the script context for context-aware hook autocomplete + activeArea.setScriptContext(getScriptContext()); + // Setup fullscreen key binding GuiScriptTextArea.KEYS.FULLSCREEN.setTask(e -> { if (e.isPress()) { @@ -627,96 +631,6 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb return ScriptContext.GLOBAL; } - // ==================== UNIFIED SCRIPT DATA HANDLING ==================== - - /** - * Unified setGuiData for script GUIs with old container system. - * Handles both language data and tab-specific script loading. - */ - protected void setGuiDataWithOldContainer(NBTTagCompound compound) { - if (compound.hasKey("LoadComplete")) { - loaded = true; - return; - } - - if (!compound.hasKey("Tab")) { - this.handler.setLanguage(compound.getString("ScriptLanguage")); - this.handler.setEnabled(compound.getBoolean("ScriptEnabled")); - this.loadLanguagesData(compound); - } else { - int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(this.handler); - container.readFromNBT(compound.getCompoundTag("Script")); - this.setHandlerContainer(container); - this.initGui(); - } - } - - /** - * Load languages data from NBT. - * Separated for potential override in subclasses if needed. - */ - protected void loadLanguagesData(NBTTagCompound compound) { - NBTTagList data = compound.getTagList("Languages", 10); - HashMap languages = new HashMap(); - - for (int i = 0; i < data.tagCount(); ++i) { - NBTTagCompound comp = data.getCompoundTagAt(i); - java.util.ArrayList scripts = new java.util.ArrayList(); - NBTTagList list = comp.getTagList("Scripts", 8); - - for (int j = 0; j < list.tagCount(); ++j) { - scripts.add(list.getStringTagAt(j)); - } - - languages.put(comp.getString("Language"), scripts); - } - - this.languages = languages; - this.initGui(); - } - - /** - * Set the handler's container. Override if handler is not IScriptHandler. - */ - protected void setHandlerContainer(IScriptUnit container) { - // Default implementation - subclasses may need to cast and set differently - // e.g., ((LinkedItemScript) handler).container = container; - } - - /** - * Unified save method for script GUIs with packet-based saving. - * Subclasses only need to override sendScriptPackets() and sendMetadataPacket(). - */ - protected void saveWithPackets() { - if (loaded) { - this.setScript(); - - List containers = this.handler.getScripts(); - for (int i = 0; i < containers.size(); i++) { - IScriptUnit container = containers.get(i); - sendSavePacket(i, containers.size(), container.writeToNBT(new NBTTagCompound())); - } - - NBTTagCompound scriptData = new NBTTagCompound(); - scriptData.setString("ScriptLanguage", this.handler.getLanguage()); - scriptData.setBoolean("ScriptEnabled", this.handler.getEnabled()); - scriptData.setTag("ScriptConsole", noppes.npcs.NBTTags.NBTLongStringMap(this.handler.getConsoleText())); - - sendSavePacket(-1, containers.size(), scriptData); - } - } - - /** - * Send a script container packet. Override in subclasses. - * @param index The index of this script - * @param totalCount Total number of scripts - * @param scriptNBT The script container NBT data - */ - protected void sendSavePacket(int index, int totalCount, NBTTagCompound scriptNBT) { - // Default: do nothing (for non-packet-based GUIs like GuiScriptItem) - } - public void save() { if (loaded) this.setScript(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java index cb5b807f2..5d23aca89 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java @@ -6,9 +6,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.CustomItems; import noppes.npcs.NBTTags; -import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.constants.ScriptContext; -import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.scripted.item.ScriptCustomItem; import java.util.*; @@ -37,6 +35,11 @@ public class GuiScriptItem extends GuiScriptInterface { } } + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.ITEM; + } + public void save() { if (loaded) { super.save(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java index 2befb8d74..755f56f56 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java @@ -4,7 +4,8 @@ import kamkeel.npcs.network.packets.request.script.PlayerScriptPacket; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.NBTTags; -import noppes.npcs.api.handler.IScriptHookHandler; +import noppes.npcs.constants.ScriptContext; +import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.data.EffectScript; import noppes.npcs.controllers.data.IScriptUnit; @@ -47,6 +48,11 @@ public class GuiScriptPlayers extends GuiScriptInterface { } } + @Override + protected ScriptContext getScriptContext() { + return ScriptContext.PLAYER; + } + public void save() { if (loaded) { super.save(); diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java index 3426bcae8..5f3e590f0 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java @@ -11,6 +11,7 @@ import noppes.npcs.client.gui.util.key.OverlayKeyPresetViewer; import noppes.npcs.client.gui.util.script.*; import noppes.npcs.client.gui.util.script.JavaTextContainer.LineData; import noppes.npcs.client.key.impl.ScriptEditorKeys; +import noppes.npcs.constants.ScriptContext; import noppes.npcs.util.ValueUtil; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; @@ -2159,6 +2160,27 @@ public class GuiScriptTextArea extends GuiNpcTextField { this.container.formatCodeText(); } + /** + * Set the script context (NPC, PLAYER, BLOCK, ITEM, etc.). + * This determines which hooks and event types are available for autocomplete. + * + * @param context The script context + */ + public void setScriptContext(ScriptContext context) { + if (this.container != null) { + this.container.setScriptContext(context); + } + } + + /** + * Get the current script context. + * + * @return The script context (NPC, PLAYER, BLOCK, ITEM, etc.) + */ + public ScriptContext getScriptContext() { + return this.container != null ? this.container.getScriptContext() : ScriptContext.GLOBAL; + } + public void setListener(ITextChangeListener listener) { this.listener = listener; } diff --git a/src/main/java/noppes/npcs/constants/ScriptContext.java b/src/main/java/noppes/npcs/constants/ScriptContext.java new file mode 100644 index 000000000..a4567955b --- /dev/null +++ b/src/main/java/noppes/npcs/constants/ScriptContext.java @@ -0,0 +1,201 @@ +package noppes.npcs.constants; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Represents a script context that maps to one or more event interface namespaces. + * + * A script context can have multiple namespaces because script editors often + * support hooks from multiple event types. For example, Player scripts support: + * - IPlayerEvent (core player hooks) + * - IAnimationEvent (animation hooks) + * - IPartyEvent (party hooks) + * - ICustomGuiEvent (custom GUI hooks) + * - etc. + * + * This is a registerable system - any mod can register their own contexts: + * + * // Register a new context with multiple namespaces: + * ScriptContext.register("DBC", "IDBCEvent", "IDBCPlayerEvent", "IDBCFormEvent"); + * + * // Or add namespaces to an existing context: + * ScriptContext.PLAYER.addNamespace("IDBCPlayerEvent"); + */ +public class ScriptContext { + + // Registry of all script contexts + private static final Map REGISTRY = new ConcurrentHashMap<>(); + + // ==================== BUILT-IN CONTEXTS ==================== + + public static final ScriptContext NPC = register("NPC", + "INpcEvent", + "IProjectileEvent" + ); + + public static final ScriptContext PLAYER = register("PLAYER", + "IPlayerEvent", + "IAnimationEvent", + "IPartyEvent", + "IDialogEvent", + "IQuestEvent", + "IFactionEvent", + "ICustomGuiEvent", + "IEffectEvent" + ); + + public static final ScriptContext BLOCK = register("BLOCK", + "IBlockEvent" + ); + + public static final ScriptContext ITEM = register("ITEM", + "IItemEvent" + ); + + public static final ScriptContext FORGE = register("FORGE", + "IForgeEvent" + ); + + public static final ScriptContext GLOBAL = register("GLOBAL", + "Global" + ); + + // ==================== INSTANCE FIELDS ==================== + + /** Unique identifier for this context (e.g., "NPC", "PLAYER", "DBC") */ + public final String id; + + /** The event interface namespaces this context supports */ + private final List namespaces; + + // ==================== CONSTRUCTOR ==================== + + private ScriptContext(String id, String... namespaces) { + this.id = id; + this.namespaces = new ArrayList<>(Arrays.asList(namespaces)); + } + + // ==================== NAMESPACE ACCESS ==================== + + /** + * Get all namespaces this context supports. + * + * @return Unmodifiable list of namespace strings + */ + public List getNamespaces() { + return Collections.unmodifiableList(namespaces); + } + + /** + * Check if this context includes a specific namespace. + * + * @param namespace The namespace to check (e.g., "IPlayerEvent") + * @return true if this context supports hooks from that namespace + */ + public boolean hasNamespace(String namespace) { + return namespaces.contains(namespace); + } + + /** + * Add a namespace to this context. + * Mods can use this to extend built-in contexts with their own event types. + * + * @param namespace The namespace to add (e.g., "IDBCPlayerEvent") + */ + public void addNamespace(String namespace) { + if (!namespaces.contains(namespace)) { + namespaces.add(namespace); + } + } + + /** + * Get the primary namespace (first one registered). + * This is mainly for backward compatibility. + * + * @return The first namespace, or "Global" if none + */ + public String getPrimaryNamespace() { + return namespaces.isEmpty() ? "Global" : namespaces.get(0); + } + + // ==================== REGISTRATION API ==================== + + /** + * Register a new script context with one or more namespaces. + * + * @param id Unique identifier (e.g., "DBC", "CUSTOM") + * @param namespaces The event interface names (e.g., "IDBCEvent", "IDBCPlayerEvent") + * @return The registered ScriptContext + */ + public static ScriptContext register(String id, String... namespaces) { + ScriptContext context = new ScriptContext(id, namespaces); + REGISTRY.put(id, context); + return context; + } + + /** + * Get a script context by its ID. + * + * @param id The context ID (e.g., "NPC", "PLAYER", "DBC") + * @return The ScriptContext, or GLOBAL if not found + */ + public static ScriptContext byId(String id) { + return REGISTRY.getOrDefault(id, GLOBAL); + } + + /** + * Find a script context that contains a specific namespace. + * + * @param namespace The event interface namespace (e.g., "INpcEvent") + * @return The first ScriptContext that contains this namespace, or GLOBAL if not found + */ + public static ScriptContext byNamespace(String namespace) { + if (namespace == null) return GLOBAL; + for (ScriptContext ctx : REGISTRY.values()) { + if (ctx.hasNamespace(namespace)) { + return ctx; + } + } + return GLOBAL; + } + + /** + * Get all registered script contexts. + * + * @return Unmodifiable collection of all registered contexts + */ + public static Collection values() { + return Collections.unmodifiableCollection(REGISTRY.values()); + } + + /** + * Check if a context with the given ID exists. + * + * @param id The context ID to check + * @return true if registered + */ + public static boolean exists(String id) { + return REGISTRY.containsKey(id); + } + + // ==================== OBJECT METHODS ==================== + + @Override + public String toString() { + return id + " -> " + namespaces; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ScriptContext)) return false; + ScriptContext other = (ScriptContext) obj; + return id.equals(other.id); + } + + @Override + public int hashCode() { + return id.hashCode(); + } +} From fd0e20f3647e699d07199ac48a6db4d57032a9b5 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 10 Jan 2026 06:53:48 +0200 Subject: [PATCH 06/19] Made ScriptContext class based instead --- .../noppes/npcs/constants/ScriptContext.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/main/java/noppes/npcs/constants/ScriptContext.java b/src/main/java/noppes/npcs/constants/ScriptContext.java index a4567955b..942c406e6 100644 --- a/src/main/java/noppes/npcs/constants/ScriptContext.java +++ b/src/main/java/noppes/npcs/constants/ScriptContext.java @@ -1,5 +1,7 @@ package noppes.npcs.constants; +import noppes.npcs.api.event.*; + import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -30,35 +32,34 @@ public class ScriptContext { // ==================== BUILT-IN CONTEXTS ==================== public static final ScriptContext NPC = register("NPC", - "INpcEvent", - "IProjectileEvent" + INpcEvent.class, + IProjectileEvent.class ); public static final ScriptContext PLAYER = register("PLAYER", - "IPlayerEvent", - "IAnimationEvent", - "IPartyEvent", - "IDialogEvent", - "IQuestEvent", - "IFactionEvent", - "ICustomGuiEvent", - "IEffectEvent" + IPlayerEvent.class, + IAnimationEvent.class, + IPartyEvent.class, + IDialogEvent.class, + IQuestEvent.class, + IFactionEvent.class, + ICustomGuiEvent.class ); public static final ScriptContext BLOCK = register("BLOCK", - "IBlockEvent" + IBlockEvent.class ); public static final ScriptContext ITEM = register("ITEM", - "IItemEvent" + IItemEvent.class ); public static final ScriptContext FORGE = register("FORGE", - "IForgeEvent" + IForgeEvent.class ); public static final ScriptContext GLOBAL = register("GLOBAL", - "Global" + "Global" // Special case: Global namespace doesn't have a corresponding event class ); // ==================== INSTANCE FIELDS ==================== @@ -134,6 +135,25 @@ public class ScriptContext { return context; } + /** + * Register a new script context using event interface classes. + * Automatically extracts the simple name from each class. + * + * Example: + * ScriptContext.register("NPC", INpcEvent.class, IProjectileEvent.class); + * + * @param id Unique identifier (e.g., "DBC", "CUSTOM") + * @param eventClasses The event interface classes (simple names will be extracted) + * @return The registered ScriptContext + */ + public static ScriptContext register(String id, Class... eventClasses) { + String[] namespaces = new String[eventClasses.length]; + for (int i = 0; i < eventClasses.length; i++) { + namespaces[i] = eventClasses[i].getSimpleName(); + } + return register(id, namespaces); + } + /** * Get a script context by its ID. * From 6173e989981be7c9d00b3df2066803df78ccbca0 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 19:05:52 +0200 Subject: [PATCH 07/19] merge conflict resolutioon --- .../client/gui/script/GuiScriptInterface.java | 92 ++++++++++++++++++- .../client/gui/script/GuiScriptPlayers.java | 4 +- 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 11c326880..d91f63c5a 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -221,7 +221,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb // Set the scripting language for proper syntax highlighting // Use the container's language if available, otherwise fall back to handler's language String language = (container != null) ? container.getLanguage() : this.handler.getLanguage(); - activeArea.setLanguage(language); + // activeArea.setLanguage(language); // Set the script context for context-aware hook autocomplete activeArea.setScriptContext(getScriptContext()); @@ -631,6 +631,96 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb return ScriptContext.GLOBAL; } + // ==================== UNIFIED SCRIPT DATA HANDLING ==================== + + /** + * Unified setGuiData for script GUIs with old container system. + * Handles both language data and tab-specific script loading. + */ + protected void setGuiDataWithOldContainer(NBTTagCompound compound) { + if (compound.hasKey("LoadComplete")) { + loaded = true; + return; + } + + if (!compound.hasKey("Tab")) { + this.handler.setLanguage(compound.getString("ScriptLanguage")); + this.handler.setEnabled(compound.getBoolean("ScriptEnabled")); + this.loadLanguagesData(compound); + } else { + int tab = compound.getInteger("Tab"); + ScriptContainer container = new ScriptContainer(this.handler); + container.readFromNBT(compound.getCompoundTag("Script")); + this.setHandlerContainer(container); + this.initGui(); + } + } + + /** + * Load languages data from NBT. + * Separated for potential override in subclasses if needed. + */ + protected void loadLanguagesData(NBTTagCompound compound) { + NBTTagList data = compound.getTagList("Languages", 10); + HashMap languages = new HashMap(); + + for (int i = 0; i < data.tagCount(); ++i) { + NBTTagCompound comp = data.getCompoundTagAt(i); + java.util.ArrayList scripts = new java.util.ArrayList(); + NBTTagList list = comp.getTagList("Scripts", 8); + + for (int j = 0; j < list.tagCount(); ++j) { + scripts.add(list.getStringTagAt(j)); + } + + languages.put(comp.getString("Language"), scripts); + } + + this.languages = languages; + this.initGui(); + } + + /** + * Set the handler's container. Override if handler is not IScriptHandler. + */ + protected void setHandlerContainer(IScriptUnit container) { + // Default implementation - subclasses may need to cast and set differently + // e.g., ((LinkedItemScript) handler).container = container; + } + + /** + * Unified save method for script GUIs with packet-based saving. + * Subclasses only need to override sendScriptPackets() and sendMetadataPacket(). + */ + protected void saveWithPackets() { + if (loaded) { + this.setScript(); + + List containers = this.handler.getScripts(); + for (int i = 0; i < containers.size(); i++) { + IScriptUnit container = containers.get(i); + sendSavePacket(i, containers.size(), container.writeToNBT(new NBTTagCompound())); + } + + NBTTagCompound scriptData = new NBTTagCompound(); + scriptData.setString("ScriptLanguage", this.handler.getLanguage()); + scriptData.setBoolean("ScriptEnabled", this.handler.getEnabled()); + scriptData.setTag("ScriptConsole", noppes.npcs.NBTTags.NBTLongStringMap(this.handler.getConsoleText())); + + sendSavePacket(-1, containers.size(), scriptData); + } + } + + /** + * Send a script container packet. Override in subclasses. + * @param index The index of this script + * @param totalCount Total number of scripts + * @param scriptNBT The script container NBT data + */ + protected void sendSavePacket(int index, int totalCount, NBTTagCompound scriptNBT) { + // Default: do nothing (for non-packet-based GUIs like GuiScriptItem) + } + public void save() { if (loaded) this.setScript(); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java index 755f56f56..3965c4e33 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java @@ -4,10 +4,10 @@ import kamkeel.npcs.network.packets.request.script.PlayerScriptPacket; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.NBTTags; +import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.constants.ScriptContext; -import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptContainer; -import noppes.npcs.controllers.data.EffectScript; +import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.controllers.data.PlayerDataScript; From 1df05406c8bb2f4057f8a8377266159130abb908 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 19:08:29 +0200 Subject: [PATCH 08/19] Imported temp place holders from syntax-highlighter-unified --- .../npcs/client/gui/script/GuiScriptInterface.java | 2 +- .../npcs/client/gui/util/GuiScriptTextArea.java | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index d91f63c5a..b2da09a40 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -221,7 +221,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb // Set the scripting language for proper syntax highlighting // Use the container's language if available, otherwise fall back to handler's language String language = (container != null) ? container.getLanguage() : this.handler.getLanguage(); - // activeArea.setLanguage(language); + activeArea.setLanguage(language); // Set the script context for context-aware hook autocomplete activeArea.setScriptContext(getScriptContext()); diff --git a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java index 5f3e590f0..99e6ce480 100644 --- a/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java +++ b/src/main/java/noppes/npcs/client/gui/util/GuiScriptTextArea.java @@ -448,6 +448,15 @@ public class GuiScriptTextArea extends GuiNpcTextField { public boolean fullscreen() { return GuiScriptInterface.isFullscreen; } + + public void setLanguage(String language) { + if (this.container != null) { + // this.container.setLanguage(language); + if (this.enableCodeHighlighting) { + this.container.formatCodeText(); + } + } + } // ==================== RENDERING ==================== public void drawTextBox(int xMouse, int yMouse) { if (!visible) @@ -2168,7 +2177,7 @@ public class GuiScriptTextArea extends GuiNpcTextField { */ public void setScriptContext(ScriptContext context) { if (this.container != null) { - this.container.setScriptContext(context); + // this.container.setScriptContext(context); } } @@ -2178,7 +2187,8 @@ public class GuiScriptTextArea extends GuiNpcTextField { * @return The script context (NPC, PLAYER, BLOCK, ITEM, etc.) */ public ScriptContext getScriptContext() { - return this.container != null ? this.container.getScriptContext() : ScriptContext.GLOBAL; + // return this.container != null ? this.container.getScriptContext() : ScriptContext.GLOBAL; + return ScriptContext.GLOBAL; } public void setListener(ITextChangeListener listener) { From 8c8f37e75d24c45dfdfee9751715a008c272387e Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 19:13:31 +0200 Subject: [PATCH 09/19] more merge conflict resolution --- src/main/java/noppes/npcs/client/gui/GuiScript.java | 6 +++--- .../java/noppes/npcs/client/gui/script/GuiScriptBlock.java | 1 + .../noppes/npcs/client/gui/script/GuiScriptInterface.java | 2 +- .../java/noppes/npcs/client/gui/script/GuiScriptItem.java | 2 ++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/GuiScript.java b/src/main/java/noppes/npcs/client/gui/GuiScript.java index 4349b1ef6..83f38b011 100644 --- a/src/main/java/noppes/npcs/client/gui/GuiScript.java +++ b/src/main/java/noppes/npcs/client/gui/GuiScript.java @@ -184,7 +184,7 @@ public class GuiScript extends GuiScriptInterface { scroll.setList(container.scripts); addScroll(scroll); } - } + private void initSettingsView() { addLabel(new GuiNpcLabel(0, "script.console", guiLeft + 4, guiTop + 16)); @@ -323,8 +323,8 @@ public class GuiScript extends GuiScriptInterface { public void mouseClicked(int mouseX, int mouseY, int mouseButton) { // Check if click is within autocomplete menu bounds and consume it if so GuiScriptTextArea activeArea = getActiveScriptArea(); - boolean isOverAutocomplete = activeArea != null - && activeArea.isPointOnAutocompleteMenu(mouseX, mouseY); + boolean isOverAutocomplete = activeArea != null; + // && activeArea.isPointOnAutocompleteMenu(mouseX, mouseY); if (isOverAutocomplete) { activeArea.mouseClicked(mouseX, mouseY, mouseButton); return; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java index 5b9762a96..b11947ee7 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptBlock.java @@ -5,6 +5,7 @@ import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.blocks.tiles.TileScripted; import noppes.npcs.constants.ScriptContext; +import noppes.npcs.controllers.ScriptHookController; import java.util.ArrayList; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index b2da09a40..90e7e7d06 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -79,7 +79,7 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb } /** Fullscreen toggle button drawn at top-right of viewport */ - private final FullscreenButton fullscreenButton = new FullscreenButton(); + public final FullscreenButton fullscreenButton = new FullscreenButton(); public GuiScriptInterface() { this.drawDefaultBackground = true; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java index 5d23aca89..fceaeb6ed 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptItem.java @@ -6,7 +6,9 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.CustomItems; import noppes.npcs.NBTTags; +import noppes.npcs.api.handler.IScriptHookHandler; import noppes.npcs.constants.ScriptContext; +import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.scripted.item.ScriptCustomItem; import java.util.*; From 7b811bdea1b8144cdf4aead489c95091b0e4fa02 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 19:16:58 +0200 Subject: [PATCH 10/19] more bruh --- .../client/gui/script/GuiJaninoScript.java | 2 +- .../client/gui/script/SubGuiSelectList.java | 123 ++++++++++++++++++ 2 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 src/main/java/noppes/npcs/client/gui/script/SubGuiSelectList.java diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiJaninoScript.java b/src/main/java/noppes/npcs/client/gui/script/GuiJaninoScript.java index 874beca4b..2f609b205 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiJaninoScript.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiJaninoScript.java @@ -1,6 +1,6 @@ package noppes.npcs.client.gui.script; -import kamkeel.npcdbc.client.gui.component.SubGuiSelectList; + import noppes.npcs.janino.JaninoScript; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.*; diff --git a/src/main/java/noppes/npcs/client/gui/script/SubGuiSelectList.java b/src/main/java/noppes/npcs/client/gui/script/SubGuiSelectList.java new file mode 100644 index 000000000..e2812ecb2 --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/script/SubGuiSelectList.java @@ -0,0 +1,123 @@ +package noppes.npcs.client.gui.script; + +import net.minecraft.client.gui.GuiButton; +import noppes.npcs.client.gui.util.GuiCustomScroll; +import noppes.npcs.client.gui.util.GuiMenuTopButton; +import noppes.npcs.client.gui.util.GuiNpcButton; +import noppes.npcs.client.gui.util.GuiNpcLabel; +import noppes.npcs.client.gui.util.SubGuiInterface; + +import java.util.ArrayList; +import java.util.List; + +public class SubGuiSelectList extends SubGuiInterface { + private GuiCustomScroll scroll1; + private GuiCustomScroll scroll2; + + public String allName, selectedName; + public List all; + public List selected; + + public SubGuiSelectList(List all, List selected, String allName, String selectedName) { + setBackground("menubg.png"); + xSize = 346; + ySize = 216; + this.allName = allName; + this.selectedName = selectedName; + + if (all == null) + all = new ArrayList<>(); + this.all = all; + + if (selected == null) + selected = new ArrayList<>(); + this.selected = selected; + } + + @Override + public void initGui() { + super.initGui(); + if (scroll1 == null) { + scroll1 = new GuiCustomScroll(this, 0); + scroll1.setSize(140, 180); + } + + addTopButton(new GuiMenuTopButton(-1, guiLeft + xSize-22 , guiTop - 17, "X")); + + scroll1.guiLeft = guiLeft + 4; + scroll1.guiTop = guiTop + 14; + this.addScroll(scroll1); + addLabel(new GuiNpcLabel(1, allName, guiLeft + 4, guiTop + 4)); + + if (scroll2 == null) { + scroll2 = new GuiCustomScroll(this, 1); + scroll2.setSize(140, 180); + } + scroll2.guiLeft = guiLeft + 200; + scroll2.guiTop = guiTop + 14; + this.addScroll(scroll2); + addLabel(new GuiNpcLabel(2, selectedName, guiLeft + 200, guiTop + 4)); + + List tempAll = new ArrayList<>(all); + tempAll.removeAll(selected); + scroll1.setList(tempAll); + scroll2.setList(selected); + + addButton(new GuiNpcButton(1, guiLeft + 145, guiTop + 40, 55, 20, ">")); + addButton(new GuiNpcButton(2, guiLeft + 145, guiTop + 62, 55, 20, "<")); + + addButton(new GuiNpcButton(3, guiLeft + 145, guiTop + 90, 55, 20, ">>")); + addButton(new GuiNpcButton(4, guiLeft + 145, guiTop + 112, 55, 20, "<<")); + + addButton(new GuiNpcButton(66, guiLeft + 260, guiTop + 194, 60, 20, "gui.done")); + } + + protected void actionPerformed(GuiButton guibutton) { + GuiNpcButton button = (GuiNpcButton) guibutton; + + if (button.id == -1) { + close(); + return; + } + + if (button.id == 1) { + if (scroll1.hasSelected()) { + selected.add(scroll1.getSelected()); + + scroll1.selected = -1; + scroll2.selected = -1; + initGui(); + } + } + if (button.id == 2) { + if (scroll2.hasSelected()) { + selected.remove(scroll2.getSelected()); + scroll2.selected = -1; + initGui(); + } + } + if (button.id == 3) { + selected.clear(); + for (String type : all) + selected.add(type); + + scroll1.selected = -1; + scroll2.selected = -1; + initGui(); + } + if (button.id == 4) { + selected.clear(); + scroll1.selected = -1; + scroll2.selected = -1; + initGui(); + } + if (button.id == 66) { + close(); + } + } + + @Override + public void save() { + + } +} From ba6c3e607c5dfd41434a26e3cd6788ead7cc5985 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 20:30:01 +0200 Subject: [PATCH 11/19] more bruh 2 --- .../java/noppes/npcs/client/gui/script/GuiScriptEffect.java | 3 ++- .../noppes/npcs/client/gui/script/GuiScriptLinkedItem.java | 3 ++- .../java/noppes/npcs/client/gui/script/GuiScriptRecipe.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java index bd5f59b1e..e50b31ade 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptEffect.java @@ -9,6 +9,7 @@ import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; import noppes.npcs.controllers.data.CustomEffect; import noppes.npcs.controllers.data.EffectScript; +import noppes.npcs.controllers.data.IScriptUnit; import java.util.ArrayList; @@ -35,7 +36,7 @@ public class GuiScriptEffect extends GuiScriptInterface { return ScriptContext.GLOBAL; } - protected void setHandlerContainer(ScriptContainer container) { + protected void setHandlerContainer(IScriptUnit container) { this.scriptHandler.container = container; } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java index d00c7b2c3..2a001b732 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptLinkedItem.java @@ -8,6 +8,7 @@ import noppes.npcs.constants.EnumScriptType; import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.controllers.data.LinkedItem; import noppes.npcs.controllers.data.LinkedItemScript; @@ -34,7 +35,7 @@ public class GuiScriptLinkedItem extends GuiScriptInterface { return ScriptContext.ITEM; } - protected void setHandlerContainer(ScriptContainer container) { + protected void setHandlerContainer(IScriptUnit container) { ((LinkedItemScript) handler).container = container; } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java index 262151d5c..176294f7e 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptRecipe.java @@ -7,6 +7,7 @@ import noppes.npcs.client.gui.global.GuiNpcManageRecipes; import noppes.npcs.constants.ScriptContext; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptHookController; +import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.controllers.data.RecipeAnvil; import noppes.npcs.controllers.data.RecipeCarpentry; import noppes.npcs.controllers.data.RecipeScript; @@ -48,7 +49,7 @@ public class GuiScriptRecipe extends GuiScriptInterface { return ScriptContext.GLOBAL; } - protected void setHandlerContainer(ScriptContainer container) { + protected void setHandlerContainer(IScriptUnit container) { ((RecipeScript) handler).container = container; } From 275cca70c23a810bfbc8199192f6cb707ede4b61 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 20:59:54 +0200 Subject: [PATCH 12/19] Redundant mouseClicked in GuiScript --- .../noppes/npcs/client/gui/GuiScript.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/GuiScript.java b/src/main/java/noppes/npcs/client/gui/GuiScript.java index 83f38b011..916a0ecd3 100644 --- a/src/main/java/noppes/npcs/client/gui/GuiScript.java +++ b/src/main/java/noppes/npcs/client/gui/GuiScript.java @@ -318,26 +318,6 @@ public class GuiScript extends GuiScriptInterface { container.script = text; } } - - @Override - public void mouseClicked(int mouseX, int mouseY, int mouseButton) { - // Check if click is within autocomplete menu bounds and consume it if so - GuiScriptTextArea activeArea = getActiveScriptArea(); - boolean isOverAutocomplete = activeArea != null; - // && activeArea.isPointOnAutocompleteMenu(mouseX, mouseY); - if (isOverAutocomplete) { - activeArea.mouseClicked(mouseX, mouseY, mouseButton); - return; - } - - // Check fullscreen button when in script view - if (showScript && !isOverAutocomplete - && fullscreenButton.mouseClicked(mouseX, mouseY, mouseButton)) { - return; - } - - super.mouseClicked(mouseX, mouseY, mouseButton); - } @Override public void setGuiData(NBTTagCompound compound) { From 92cd894f39187df9c5965d12f76a2facc56abf62 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 21:39:04 +0200 Subject: [PATCH 13/19] Improved JaninoScript hook generation --- .../java/noppes/npcs/janino/JaninoScript.java | 87 ++++++++++++++++--- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/src/main/java/noppes/npcs/janino/JaninoScript.java b/src/main/java/noppes/npcs/janino/JaninoScript.java index 5fb02a46e..bac0b1cf8 100644 --- a/src/main/java/noppes/npcs/janino/JaninoScript.java +++ b/src/main/java/noppes/npcs/janino/JaninoScript.java @@ -46,6 +46,12 @@ public abstract class JaninoScript implements IScriptUnit { public final IScriptBodyBuilder builder; protected IScriptClassBody scriptBody; + private boolean hooksInitialized = false; + // Hook list for GUI display + private List hookList = new ArrayList<>(); + // Map from display name (with parameters if overloaded) to Method + private Map hookMap = new HashMap<>(); + protected JaninoScript(Class type, Consumer> buildSettings) { this.type = type; this.builder = IScriptBodyBuilder @@ -257,15 +263,22 @@ public abstract class JaninoScript implements IScriptUnit { return true; return script != null && !script.isEmpty(); } - + @Override public String generateHookStub(String hookName, Object hookData) { - // If hookData is a Method, generate full Java method stub - if (hookData instanceof Method) { - return generateMethodStub((Method) hookData); + // Build hook list and map + if (!hooksInitialized) { + createHookList(); + hooksInitialized = true; } - // Fallback for simple hook names - generate basic override - return String.format("@Override\npublic void %s() {\n \n}\n", hookName); + + // Look up in hookMap (handles both simple names and overloaded display names) + Method method = hookMap.get(hookName); + if (method != null) + return generateMethodStub(method); + + // Fallback for unknown hook names - generate basic override + return String.format("public void %s() {\n \n}\n", hookName); } /** @@ -285,12 +298,22 @@ public abstract class JaninoScript implements IScriptUnit { String params = Arrays.stream(method.getParameters()) .map(p -> { String typeName = p.getType().getSimpleName(); - String baseName = Character.toLowerCase(typeName.charAt(0)) + typeName.substring(1); - int count = typeCount.getOrDefault(baseName, 0) + 1; - typeCount.put(baseName, count); + // Check for @ParamName annotation first + ParamName paramNameAnnotation = p.getAnnotation(ParamName.class); + String paramName; - String paramName = count == 1 ? baseName : baseName + (count - 1); + if (paramNameAnnotation != null) { + // Use annotated name + paramName = paramNameAnnotation.value(); + } else { + // Fall back to generated name + String baseName = Character.toLowerCase(typeName.charAt(0)) + typeName.substring(1); + int count = typeCount.getOrDefault(baseName, 0) + 1; + typeCount.put(baseName, count); + paramName = count == 1 ? baseName : baseName + (count - 1); + } + return typeName + " " + paramName; }) .collect(Collectors.joining(", ")); @@ -310,7 +333,49 @@ public abstract class JaninoScript implements IScriptUnit { body = " return null;"; } - return String.format("@Override\n%s%s %s(%s) {\n%s\n}\n", mods, returnTypeStr, name, params, body); + return String.format("%s%s %s(%s) {\n%s\n}\n", mods, returnTypeStr, name, params, body); + } + + + /** + * Create the hook list and hook map for GUI display and generation. + * Groups methods by name and creates display names with parameters for overloaded methods. + */ + private void createHookList() { + // Group all declared methods by their name + Map> grouped = Arrays.stream(type.getDeclaredMethods()) + .collect(Collectors.groupingBy(Method::getName)); + + for (Map.Entry> entry : grouped.entrySet()) { + List methods = entry.getValue(); + + // Sort overloads by parameter count (ascending) + methods.sort(Comparator.comparingInt(Method::getParameterCount)); + boolean first = true; + + for (Method m : methods) { + if (Modifier.isFinal(m.getModifiers())) + continue; // Skip final methods + + // For first (simplest) overload, use just the method name + // For additional overloads, include parameter types in display name + String displayName = first ? m.getName() : + m.getName() + "(" + Arrays.stream(m.getParameterTypes()) + .map(Class::getSimpleName) + .collect(Collectors.joining(", ")) + ")"; + + hookList.add(displayName); + hookMap.put(displayName, m); + first = false; + } + } + } + + /** + * Get the list of hook names for GUI display. + */ + public List getHookList() { + return new ArrayList<>(hookList); } From fbcda09fe24623fd7371b70a41db0a30d2cbb2af Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 21:39:39 +0200 Subject: [PATCH 14/19] Used IScriptUnit hook stub generation --- .../npcs/client/gui/script/GuiScriptInterface.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 90e7e7d06..12f0a21f2 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -332,10 +332,17 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb public void customScrollClicked(int i, int j, int k, GuiCustomScroll scroll) { String hook = scroll.getSelected(); if (previousHookClicked.equals(hook)) { + IScriptUnit container = getCurrentContainer(); + if (container == null) + return; + String addString = ""; if (!this.getTextField(2).getText().isEmpty()) addString += "\n"; - addString += "function " + hook + "(event) {\n \n}\n"; + + // Generate the appropriate stub based on language + // hook is already the proper method name from EnumScriptType.function + addString += container.generateHookStub(hook, null); this.getTextField(2).setText(this.getTextField(2).getText() + addString); previousHookClicked = ""; From 73db727c471cf6dc289a844bae473fecf8d4827b Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 22:16:51 +0200 Subject: [PATCH 15/19] Deleagted all ScriptContainer NBT based creation to IScriptUnit.createFromNBT --- .../java/kamkeel/npcs/network/PacketUtil.java | 4 +-- src/main/java/noppes/npcs/NBTTags.java | 6 ++-- .../client/gui/script/GuiNPCEventScripts.java | 4 +-- .../client/gui/script/GuiScriptAllNPCs.java | 4 +-- .../client/gui/script/GuiScriptForge.java | 4 +-- .../client/gui/script/GuiScriptInterface.java | 4 +-- .../client/gui/script/GuiScriptPlayers.java | 4 +-- .../npcs/controllers/ScriptContainer.java | 1 + .../npcs/controllers/data/EffectScript.java | 7 ++-- .../npcs/controllers/data/IScriptUnit.java | 35 +++++++++++++++++++ .../controllers/data/LinkedItemScript.java | 7 ++-- .../controllers/data/PlayerDataScript.java | 9 +++-- .../npcs/controllers/data/RecipeScript.java | 7 ++-- .../java/noppes/npcs/janino/JaninoScript.java | 1 + 14 files changed, 61 insertions(+), 36 deletions(-) diff --git a/src/main/java/kamkeel/npcs/network/PacketUtil.java b/src/main/java/kamkeel/npcs/network/PacketUtil.java index cb2881eb8..9235dc1f7 100644 --- a/src/main/java/kamkeel/npcs/network/PacketUtil.java +++ b/src/main/java/kamkeel/npcs/network/PacketUtil.java @@ -251,8 +251,8 @@ public class PacketUtil { data.getScripts().add(new ScriptContainer(data)); } NBTTagCompound tabCompound = ByteBufUtils.readNBT(buffer); - ScriptContainer script = new ScriptContainer(data); - script.readFromNBT(tabCompound); + // Use factory method to create correct script unit type based on NBT + IScriptUnit script = IScriptUnit.createFromNBT(tabCompound, data); data.getScripts().set(tab, script); } else { NBTTagCompound compound = ByteBufUtils.readNBT(buffer); diff --git a/src/main/java/noppes/npcs/NBTTags.java b/src/main/java/noppes/npcs/NBTTags.java index 21e751f11..fff8d1c5d 100644 --- a/src/main/java/noppes/npcs/NBTTags.java +++ b/src/main/java/noppes/npcs/NBTTags.java @@ -546,8 +546,7 @@ public class NBTTags { for (int i = 0; i < list.tagCount(); ++i) { NBTTagCompound compoundd = list.getCompoundTagAt(i); - ScriptContainer script = new ScriptContainer(handler); - script.readFromNBT(compoundd); + IScriptUnit script = IScriptUnit.createFromNBT(compoundd, handler); scripts.add(script); } @@ -559,8 +558,7 @@ public class NBTTags { for (int i = 0; i < compound.getInteger("TotalScripts"); ++i) { NBTTagCompound containerCompound = compound.getCompoundTag("Tab" + i); - ScriptContainer script = new ScriptContainer(handler); - script.readFromNBT(containerCompound); + IScriptUnit script = IScriptUnit.createFromNBT(containerCompound, handler); scripts.add(script); } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java b/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java index 8b72bb145..e0ad70596 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiNPCEventScripts.java @@ -35,8 +35,8 @@ public class GuiNPCEventScripts extends GuiScriptInterface { super.setGuiData(compound); } else { int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(script); - container.readFromNBT(compound.getCompoundTag("Script")); + NBTTagCompound scriptCompound = compound.getCompoundTag("Script"); + IScriptUnit container = IScriptUnit.createFromNBT(scriptCompound, script); if (script.getScripts().isEmpty()) { for (int i = 0; i < compound.getInteger("TotalScripts"); i++) { script.getScripts().add(new ScriptContainer(script)); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java index 27e2f8433..71bc73d7d 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java @@ -33,8 +33,8 @@ public class GuiScriptAllNPCs extends GuiScriptInterface { super.setGuiData(compound); } else { int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(script); - container.readFromNBT(compound.getCompoundTag("Script")); + NBTTagCompound scriptCompound = compound.getCompoundTag("Script"); + IScriptUnit container = IScriptUnit.createFromNBT(scriptCompound, script); if (script.getScripts().isEmpty()) { for (int i = 0; i < compound.getInteger("TotalScripts"); i++) { script.getScripts().add(new ScriptContainer(script)); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java index d4aa8ade7..59333eee4 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptForge.java @@ -88,8 +88,8 @@ public class GuiScriptForge extends GuiScriptInterface { super.setGuiData(compound); } else { int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(script); - container.readFromNBT(compound.getCompoundTag("Script")); + NBTTagCompound scriptCompound = compound.getCompoundTag("Script"); + IScriptUnit container = IScriptUnit.createFromNBT(scriptCompound, script); if (script.getScripts().isEmpty()) { for (int i = 0; i < compound.getInteger("TotalScripts"); i++) { script.getScripts().add(new ScriptContainer(script)); diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java index 12f0a21f2..3e16377f4 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -656,8 +656,8 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb this.loadLanguagesData(compound); } else { int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(this.handler); - container.readFromNBT(compound.getCompoundTag("Script")); + NBTTagCompound scriptCompound = compound.getCompoundTag("Script"); + IScriptUnit container = IScriptUnit.createFromNBT(scriptCompound, this.handler); this.setHandlerContainer(container); this.initGui(); } diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java index 3965c4e33..de884b356 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java @@ -36,8 +36,8 @@ public class GuiScriptPlayers extends GuiScriptInterface { super.setGuiData(compound); } else { int tab = compound.getInteger("Tab"); - ScriptContainer container = new ScriptContainer(script); - container.readFromNBT(compound.getCompoundTag("Script")); + NBTTagCompound scriptCompound = compound.getCompoundTag("Script"); + IScriptUnit container = IScriptUnit.createFromNBT(scriptCompound, script); if (script.getScripts().isEmpty()) { for (int i = 0; i < compound.getInteger("TotalScripts"); i++) { script.getScripts().add(new ScriptContainer(script)); diff --git a/src/main/java/noppes/npcs/controllers/ScriptContainer.java b/src/main/java/noppes/npcs/controllers/ScriptContainer.java index 70e29df25..b85bb1407 100644 --- a/src/main/java/noppes/npcs/controllers/ScriptContainer.java +++ b/src/main/java/noppes/npcs/controllers/ScriptContainer.java @@ -70,6 +70,7 @@ public class ScriptContainer implements IScriptUnit { } public NBTTagCompound writeToNBT(NBTTagCompound compound) { + compound.setString(IScriptUnit.NBT_TYPE_KEY, IScriptUnit.TYPE_ECMASCRIPT); if (this.script.length() < 65535) { compound.setString("Script", this.script); } else { diff --git a/src/main/java/noppes/npcs/controllers/data/EffectScript.java b/src/main/java/noppes/npcs/controllers/data/EffectScript.java index 497b46421..d15e88878 100644 --- a/src/main/java/noppes/npcs/controllers/data/EffectScript.java +++ b/src/main/java/noppes/npcs/controllers/data/EffectScript.java @@ -39,8 +39,7 @@ public class EffectScript implements INpcScriptHandler { enabled = compound.getBoolean("ScriptEnabled"); if (compound.hasKey("ScriptContent", Constants.NBT.TAG_COMPOUND)) { - container = new ScriptContainer(this); - container.readFromNBT(compound.getCompoundTag("ScriptContent")); + container = IScriptUnit.createFromNBT(compound.getCompoundTag("ScriptContent"), this); } return this; } @@ -142,9 +141,7 @@ public class EffectScript implements INpcScriptHandler { if (tab == 0) { NBTTagCompound tabCompound = ByteBufUtils.readNBT(buffer); - ScriptContainer script = new ScriptContainer(this); - script.readFromNBT(tabCompound); - this.container = script; + this.container = IScriptUnit.createFromNBT(tabCompound, this); } else { NBTTagCompound compound = ByteBufUtils.readNBT(buffer); this.setLanguage(compound.getString("ScriptLanguage")); diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java index d8d280be0..fcd3fc6f8 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java @@ -1,6 +1,8 @@ package noppes.npcs.controllers.data; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.janino.JaninoScript; import java.util.List; import java.util.Map; @@ -13,6 +15,39 @@ import java.util.TreeMap; */ public interface IScriptUnit { + // NBT type identifiers + String NBT_TYPE_KEY = "ScriptUnitType"; + String TYPE_ECMASCRIPT = "ECMAScript"; + String TYPE_JANINO = "Janino"; + + /** + * Create an IScriptUnit from NBT data. + * Uses the "ScriptUnitType" tag to determine which implementation to create. + * + * @param compound The NBT data + * @param handler The script handler (used for ScriptContainer) + * @return A ScriptContainer or JaninoScript based on the NBT type + */ + static IScriptUnit createFromNBT(NBTTagCompound compound, IScriptHandler handler) { + String type = compound.getString(NBT_TYPE_KEY); + IScriptUnit unit; + + if (TYPE_JANINO.equals(type)) { + // Create appropriate JaninoScript based on handler + unit = handler.createJaninoScriptUnit(); + if (unit == null) { + // Fallback to ScriptContainer if handler doesn't support Janino + unit = new ScriptContainer(handler); + } + } else { + // Default to ScriptContainer for ECMAScript or missing type + unit = new ScriptContainer(handler); + } + + unit.readFromNBT(compound); + return unit; + } + // ==================== SCRIPT CONTENT ==================== /** diff --git a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java index 18df07229..1ef66c44a 100644 --- a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java +++ b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java @@ -37,8 +37,7 @@ public class LinkedItemScript implements INpcScriptHandler { enabled = compound.getBoolean("ScriptEnabled"); if (compound.hasKey("ScriptContent", Constants.NBT.TAG_COMPOUND)) { - container = new ScriptContainer(this); - container.readFromNBT(compound.getCompoundTag("ScriptContent")); + container = IScriptUnit.createFromNBT(compound.getCompoundTag("ScriptContent"), this); } return this; } @@ -136,9 +135,7 @@ public class LinkedItemScript implements INpcScriptHandler { if (tab == 0) { NBTTagCompound tabCompound = ByteBufUtils.readNBT(buffer); - ScriptContainer script = new ScriptContainer(this); - script.readFromNBT(tabCompound); - this.container = script; + this.container = IScriptUnit.createFromNBT(tabCompound, this); } else { NBTTagCompound compound = ByteBufUtils.readNBT(buffer); this.setLanguage(compound.getString("ScriptLanguage")); diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java index 5d2eee9f9..6aa09cd76 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java @@ -105,11 +105,10 @@ public class PlayerDataScript implements INpcScriptHandler { if (player != null) { scripts.clear(); for (IScriptUnit script : ScriptController.Instance.playerScripts.scripts) { - if (script instanceof ScriptContainer) { - ScriptContainer s = new ScriptContainer(this); - s.readFromNBT(((ScriptContainer) script).writeToNBT(new NBTTagCompound())); - scripts.add(s); - } + // Clone the script unit by writing to NBT and reading back with factory + NBTTagCompound nbt = script.writeToNBT(new NBTTagCompound()); + IScriptUnit cloned = IScriptUnit.createFromNBT(nbt, this); + scripts.add(cloned); } } lastPlayerUpdate = ScriptController.Instance.lastPlayerUpdate; diff --git a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java index b42595cf5..a021bf35f 100644 --- a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java +++ b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java @@ -35,8 +35,7 @@ public class RecipeScript implements INpcScriptHandler { scriptLanguage = compound.getString("ScriptLanguage"); enabled = compound.getBoolean("ScriptEnabled"); if (compound.hasKey("ScriptContent", Constants.NBT.TAG_COMPOUND)) { - container = new ScriptContainer(this); - container.readFromNBT(compound.getCompoundTag("ScriptContent")); + container = IScriptUnit.createFromNBT(compound.getCompoundTag("ScriptContent"), this); } return this; } @@ -131,9 +130,7 @@ public class RecipeScript implements INpcScriptHandler { this.container = null; if (tab == 0) { NBTTagCompound tabCompound = ByteBufUtils.readNBT(buffer); - ScriptContainer script = new ScriptContainer(this); - script.readFromNBT(tabCompound); - this.container = script; + this.container = IScriptUnit.createFromNBT(tabCompound, this); } else { NBTTagCompound compound = ByteBufUtils.readNBT(buffer); this.setLanguage(compound.getString("ScriptLanguage")); diff --git a/src/main/java/noppes/npcs/janino/JaninoScript.java b/src/main/java/noppes/npcs/janino/JaninoScript.java index bac0b1cf8..13a7a33c9 100644 --- a/src/main/java/noppes/npcs/janino/JaninoScript.java +++ b/src/main/java/noppes/npcs/janino/JaninoScript.java @@ -381,6 +381,7 @@ public abstract class JaninoScript implements IScriptUnit { @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { + compound.setString(IScriptUnit.NBT_TYPE_KEY, IScriptUnit.TYPE_JANINO); compound.setBoolean("enabled", enabled); compound.setTag("console", NBTTags.NBTLongStringMap(this.console)); compound.setTag("externalScripts", NBTTags.nbtStringList(this.externalScripts)); From 10b6ccf427f9a2c0969a505f54904f37af00d182 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 22:35:54 +0200 Subject: [PATCH 16/19] Converted to using IScriptUnit --- .../noppes/npcs/client/gui/GuiScriptList.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/GuiScriptList.java b/src/main/java/noppes/npcs/client/gui/GuiScriptList.java index 0d03d13cd..547f75f83 100644 --- a/src/main/java/noppes/npcs/client/gui/GuiScriptList.java +++ b/src/main/java/noppes/npcs/client/gui/GuiScriptList.java @@ -6,6 +6,7 @@ import noppes.npcs.client.gui.util.GuiNpcButton; import noppes.npcs.client.gui.util.GuiNpcLabel; import noppes.npcs.client.gui.util.SubGuiInterface; import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.controllers.data.IScriptUnit; import java.util.ArrayList; import java.util.List; @@ -13,16 +14,20 @@ import java.util.List; public class GuiScriptList extends SubGuiInterface { private GuiCustomScroll scroll1; private GuiCustomScroll scroll2; - private ScriptContainer container; + private IScriptUnit scriptUnit; private List scripts; public GuiScriptList(List scripts, ScriptContainer container) { - this.container = container; + this(scripts, (IScriptUnit) container); + } + + public GuiScriptList(List scripts, IScriptUnit scriptUnit) { + this.scriptUnit = scriptUnit; setBackground("menubg.png"); xSize = 346; ySize = 216; if (scripts == null) - scripts = new ArrayList(); + scripts = new ArrayList<>(); this.scripts = scripts; } @@ -46,10 +51,10 @@ public class GuiScriptList extends SubGuiInterface { scroll2.guiTop = guiTop + 14; this.addScroll(scroll2); addLabel(new GuiNpcLabel(2, "script.loadedScripts", guiLeft + 200, guiTop + 4)); - List temp = new ArrayList(scripts); - temp.removeAll(container.scripts); + List temp = new ArrayList<>(scripts); + temp.removeAll(scriptUnit.getExternalScripts()); scroll1.setList(temp); - scroll2.setList(container.scripts); + scroll2.setList(scriptUnit.getExternalScripts()); addButton(new GuiNpcButton(1, guiLeft + 145, guiTop + 40, 55, 20, ">")); addButton(new GuiNpcButton(2, guiLeft + 145, guiTop + 62, 55, 20, "<")); @@ -64,7 +69,7 @@ public class GuiScriptList extends SubGuiInterface { GuiNpcButton button = (GuiNpcButton) guibutton; if (button.id == 1) { if (scroll1.hasSelected()) { - container.scripts.add(scroll1.getSelected()); + scriptUnit.getExternalScripts().add(scroll1.getSelected()); scroll1.selected = -1; scroll2.selected = -1; initGui(); @@ -72,22 +77,22 @@ public class GuiScriptList extends SubGuiInterface { } if (button.id == 2) { if (scroll2.hasSelected()) { - container.scripts.remove(scroll2.getSelected()); + scriptUnit.getExternalScripts().remove(scroll2.getSelected()); scroll2.selected = -1; initGui(); } } if (button.id == 3) { - container.scripts.clear(); + scriptUnit.getExternalScripts().clear(); for (String script : scripts) { - container.scripts.add(script); + scriptUnit.getExternalScripts().add(script); } scroll1.selected = -1; scroll2.selected = -1; initGui(); } if (button.id == 4) { - container.scripts.clear(); + scriptUnit.getExternalScripts().clear(); scroll1.selected = -1; scroll2.selected = -1; initGui(); From cd60a03544d9f565541c29de7b61c906bb91b74a Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 13 Jan 2026 23:45:14 +0200 Subject: [PATCH 17/19] Moved all INpcScriptHandler implementations to IScriptHandler as its redundant --- src/main/java/noppes/npcs/EventHooks.java | 33 +++++++++---------- .../controllers/LinkedItemController.java | 4 +-- .../npcs/controllers/data/DataScript.java | 2 +- .../npcs/controllers/data/EffectScript.java | 2 +- .../controllers/data/ForgeDataScript.java | 2 +- .../controllers/data/GlobalNPCDataScript.java | 2 +- .../controllers/data/INpcScriptHandler.java | 7 ++-- .../controllers/data/IScriptBlockHandler.java | 2 +- .../npcs/controllers/data/IScriptHandler.java | 3 ++ .../controllers/data/LinkedItemScript.java | 2 +- .../controllers/data/PlayerDataScript.java | 2 +- .../npcs/controllers/data/RecipeScript.java | 2 +- .../npcs/scripted/item/ScriptCustomItem.java | 6 ++-- .../npcs/scripted/item/ScriptLinkedItem.java | 4 +-- 14 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/main/java/noppes/npcs/EventHooks.java b/src/main/java/noppes/npcs/EventHooks.java index 0dfac34ff..a0c3d2b57 100644 --- a/src/main/java/noppes/npcs/EventHooks.java +++ b/src/main/java/noppes/npcs/EventHooks.java @@ -40,7 +40,6 @@ import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.Dialog; import noppes.npcs.controllers.data.EffectScript; import noppes.npcs.controllers.data.ForgeDataScript; -import noppes.npcs.controllers.data.INpcScriptHandler; import noppes.npcs.controllers.data.IScriptBlockHandler; import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.controllers.data.Party; @@ -85,7 +84,7 @@ public class EventHooks { } public static void onScriptItemInit(IItemCustomizable item) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); if (handler != null && !handler.isClient()) { ItemEvent.InitEvent event = new ItemEvent.InitEvent(item); handler.callScript(EnumScriptType.INIT, event); @@ -94,7 +93,7 @@ public class EventHooks { } public static void onScriptItemUpdate(IItemCustomizable item, EntityLivingBase player) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); if (handler != null && !handler.isClient()) { ItemEvent.UpdateEvent event = new ItemEvent.UpdateEvent(item, NpcAPI.Instance().getIEntity(player)); handler.callScript(EnumScriptType.TICK, event); @@ -103,7 +102,7 @@ public class EventHooks { } public static boolean onScriptItemTossed(IItemCustomizable item, EntityPlayer player, EntityItem entity) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.TossedEvent event = new ItemEvent.TossedEvent(item, (IPlayer) NpcAPI.Instance().getIEntity(player), NpcAPI.Instance().getIEntity(entity)); if (handler != null) { handler.callScript(EnumScriptType.TOSSED, event); @@ -112,7 +111,7 @@ public class EventHooks { } public static boolean onScriptItemPickedUp(IItemCustomizable item, EntityPlayer player) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.PickedUpEvent event = new ItemEvent.PickedUpEvent(item, (IPlayer) NpcAPI.Instance().getIEntity(player)); if (handler != null) { handler.callScript(EnumScriptType.PICKEDUP, event); @@ -121,7 +120,7 @@ public class EventHooks { } public static boolean onScriptItemSpawn(IItemCustomizable item, EntityItem entity) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.SpawnEvent event = new ItemEvent.SpawnEvent(item, NpcAPI.Instance().getIEntity(entity)); if (handler != null) { handler.callScript(EnumScriptType.SPAWN, event); @@ -130,7 +129,7 @@ public class EventHooks { } public static boolean onScriptItemInteract(IItemCustomizable item, noppes.npcs.scripted.event.ItemEvent.InteractEvent event) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); if (handler != null) { handler.callScript(EnumScriptType.INTERACT, event); } @@ -138,7 +137,7 @@ public class EventHooks { } public static boolean onScriptItemRightClick(IItemCustomizable item, noppes.npcs.scripted.event.ItemEvent.RightClickEvent event) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); if (handler != null) { handler.callScript(EnumScriptType.RIGHT_CLICK, event); } @@ -146,7 +145,7 @@ public class EventHooks { } public static boolean onScriptItemAttack(IItemCustomizable item, noppes.npcs.scripted.event.ItemEvent.AttackEvent event) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); if (handler != null) { handler.callScript(EnumScriptType.ATTACK, event); } @@ -154,7 +153,7 @@ public class EventHooks { } public static boolean onStartUsingCustomItem(IItemCustomizable item, IPlayer player, int duration) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.StartUsingItem event = new ItemEvent.StartUsingItem(item, player, duration); if (handler != null) { handler.callScript(EnumScriptType.START_USING_ITEM, event); @@ -163,7 +162,7 @@ public class EventHooks { } public static boolean onUsingCustomItem(IItemCustomizable item, IPlayer player, int duration) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.UsingItem event = new ItemEvent.UsingItem(item, player, duration); if (handler != null) { handler.callScript(EnumScriptType.USING_ITEM, event); @@ -172,7 +171,7 @@ public class EventHooks { } public static boolean onStopUsingCustomItem(IItemCustomizable item, IPlayer player, int duration) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.StopUsingItem event = new ItemEvent.StopUsingItem(item, player, duration); if (handler != null) { handler.callScript(EnumScriptType.STOP_USING_ITEM, event); @@ -181,7 +180,7 @@ public class EventHooks { } public static boolean onFinishUsingCustomItem(IItemCustomizable item, IPlayer player, int duration) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.FinishUsingItem event = new ItemEvent.FinishUsingItem(item, player, duration); if (handler != null) { handler.callScript(EnumScriptType.FINISH_USING_ITEM, event); @@ -190,7 +189,7 @@ public class EventHooks { } public static void onRepairCustomItem(IItemCustomizable item, IPlayer player, IItemStack left, IItemStack right, float anvilBreakChance) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.RepairItem event = new ItemEvent.RepairItem(item, player, left, right, anvilBreakChance); if (handler != null) { handler.callScript(EnumScriptType.REPAIR_ITEM, event); @@ -199,7 +198,7 @@ public class EventHooks { } public static void onBreakCustomItem(IItemCustomizable item, IPlayer player) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); ItemEvent.BreakItem event = new ItemEvent.BreakItem(item, player); if (handler != null) { handler.callScript(EnumScriptType.BREAK_ITEM, event); @@ -242,7 +241,7 @@ public class EventHooks { public static void onLinkedItemVersionChange(IItemLinked item, int version, int prevVersion) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); LinkedItemEvent.VersionChangeEvent event = new LinkedItemEvent.VersionChangeEvent(item, version, prevVersion); if (handler != null) { handler.callScript(EnumScriptType.LINKED_ITEM_VERSION, event); @@ -251,7 +250,7 @@ public class EventHooks { } public static void onLinkedItemBuild(IItemLinked item) { - INpcScriptHandler handler = (INpcScriptHandler) item.getScriptHandler(); + IScriptHandler handler = (IScriptHandler) item.getScriptHandler(); LinkedItemEvent.BuildEvent event = new LinkedItemEvent.BuildEvent(item); if (handler != null) { handler.callScript(EnumScriptType.LINKED_ITEM_BUILD, event); diff --git a/src/main/java/noppes/npcs/controllers/LinkedItemController.java b/src/main/java/noppes/npcs/controllers/LinkedItemController.java index c2bc19044..48f19958b 100644 --- a/src/main/java/noppes/npcs/controllers/LinkedItemController.java +++ b/src/main/java/noppes/npcs/controllers/LinkedItemController.java @@ -7,7 +7,7 @@ import noppes.npcs.CustomNpcs; import noppes.npcs.LogWriter; import noppes.npcs.api.handler.data.ILinkedItem; import noppes.npcs.api.item.IItemStack; -import noppes.npcs.controllers.data.INpcScriptHandler; +import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.controllers.data.LinkedItem; import noppes.npcs.controllers.data.LinkedItemScript; import noppes.npcs.util.NBTJsonUtil; @@ -90,7 +90,7 @@ public class LinkedItemController { return this.linkedItems.containsValue(linkedItem); } - public INpcScriptHandler getScriptHandler(int id) { + public IScriptHandler getScriptHandler(int id) { return this.linkedItemsScripts.get(id); } diff --git a/src/main/java/noppes/npcs/controllers/data/DataScript.java b/src/main/java/noppes/npcs/controllers/data/DataScript.java index 45ba9a966..71921e60b 100644 --- a/src/main/java/noppes/npcs/controllers/data/DataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/DataScript.java @@ -35,7 +35,7 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; -public class DataScript implements INpcScriptHandler { +public class DataScript implements IScriptHandler { public List eventScripts = new ArrayList<>(); private HashMap scripts = new HashMap<>(); diff --git a/src/main/java/noppes/npcs/controllers/data/EffectScript.java b/src/main/java/noppes/npcs/controllers/data/EffectScript.java index d15e88878..5ca67697d 100644 --- a/src/main/java/noppes/npcs/controllers/data/EffectScript.java +++ b/src/main/java/noppes/npcs/controllers/data/EffectScript.java @@ -19,7 +19,7 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; -public class EffectScript implements INpcScriptHandler { +public class EffectScript implements IScriptHandler { public IScriptUnit container; public String scriptLanguage = "ECMAScript"; public boolean enabled = false; diff --git a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java index d38342f0e..66563bf54 100644 --- a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java @@ -15,7 +15,7 @@ import java.util.Map; import java.util.Map.Entry; import java.util.TreeMap; -public class ForgeDataScript implements INpcScriptHandler { +public class ForgeDataScript implements IScriptHandler { private List scripts = new ArrayList<>(); private String scriptLanguage = "ECMAScript"; public long lastInited = -1L; diff --git a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java index f21818136..4bbb742ce 100644 --- a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java @@ -26,7 +26,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; -public class GlobalNPCDataScript implements INpcScriptHandler { +public class GlobalNPCDataScript implements IScriptHandler { public List scripts = new ArrayList<>(); public String scriptLanguage = "ECMAScript"; private EntityNPCInterface npc; diff --git a/src/main/java/noppes/npcs/controllers/data/INpcScriptHandler.java b/src/main/java/noppes/npcs/controllers/data/INpcScriptHandler.java index 508836d1c..82119a6d4 100644 --- a/src/main/java/noppes/npcs/controllers/data/INpcScriptHandler.java +++ b/src/main/java/noppes/npcs/controllers/data/INpcScriptHandler.java @@ -1,8 +1,7 @@ package noppes.npcs.controllers.data; -import cpw.mods.fml.common.eventhandler.Event; -import noppes.npcs.constants.EnumScriptType; - public interface INpcScriptHandler extends IScriptHandler { - void callScript(EnumScriptType var1, Event var2); + // This interface is now empty - callScript methods moved to IScriptHandler + // Kept for backward compatibility + } diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptBlockHandler.java b/src/main/java/noppes/npcs/controllers/data/IScriptBlockHandler.java index c0445594e..f39b87112 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptBlockHandler.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptBlockHandler.java @@ -2,7 +2,7 @@ package noppes.npcs.controllers.data; import noppes.npcs.api.IBlock; -public interface IScriptBlockHandler extends INpcScriptHandler { +public interface IScriptBlockHandler extends IScriptHandler { IBlock getBlock(); } diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java b/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java index 2aa9c1db5..6b551feb9 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptHandler.java @@ -1,11 +1,14 @@ package noppes.npcs.controllers.data; import cpw.mods.fml.common.eventhandler.Event; +import noppes.npcs.constants.EnumScriptType; import java.util.List; import java.util.Map; public interface IScriptHandler { + void callScript(EnumScriptType type, Event event); + void callScript(String hookName, Event event); boolean isClient(); diff --git a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java index 1ef66c44a..d13e64c50 100644 --- a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java +++ b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java @@ -18,7 +18,7 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; -public class LinkedItemScript implements INpcScriptHandler { +public class LinkedItemScript implements IScriptHandler { public IScriptUnit container; public String scriptLanguage = "ECMAScript"; public boolean enabled = false; diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java index 6aa09cd76..7fd2eb644 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java @@ -30,7 +30,7 @@ import java.util.OptionalInt; import java.util.OptionalLong; import java.util.TreeMap; -public class PlayerDataScript implements INpcScriptHandler { +public class PlayerDataScript implements IScriptHandler { public List scripts = new ArrayList<>(); public String scriptLanguage = "ECMAScript"; private EntityPlayer player; diff --git a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java index a021bf35f..ff9f681ad 100644 --- a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java +++ b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java @@ -18,7 +18,7 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; -public class RecipeScript implements INpcScriptHandler { +public class RecipeScript implements IScriptHandler { public IScriptUnit container; public String scriptLanguage = "ECMAScript"; public boolean enabled = false; diff --git a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java index e03995e16..87d233540 100644 --- a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java +++ b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java @@ -10,7 +10,7 @@ import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.data.IScriptUnit; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; -import noppes.npcs.controllers.data.INpcScriptHandler; +import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.scripted.CustomNPCsException; import java.util.ArrayList; @@ -19,7 +19,7 @@ import java.util.Map; import java.util.Objects; import java.util.TreeMap; -public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCustom, INpcScriptHandler { +public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCustom, IScriptHandler { public List scripts = new ArrayList(); public List errored = new ArrayList(); public String scriptLanguage = "ECMAScript"; @@ -70,7 +70,7 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus } @Override - public INpcScriptHandler getScriptHandler() { + public IScriptHandler getScriptHandler() { return this; } diff --git a/src/main/java/noppes/npcs/scripted/item/ScriptLinkedItem.java b/src/main/java/noppes/npcs/scripted/item/ScriptLinkedItem.java index 3a777134c..1c4a2ac91 100644 --- a/src/main/java/noppes/npcs/scripted/item/ScriptLinkedItem.java +++ b/src/main/java/noppes/npcs/scripted/item/ScriptLinkedItem.java @@ -4,7 +4,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.api.item.IItemLinked; import noppes.npcs.controllers.LinkedItemController; -import noppes.npcs.controllers.data.INpcScriptHandler; +import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.controllers.data.LinkedItem; public class ScriptLinkedItem extends ScriptCustomizableItem implements IItemLinked { @@ -51,7 +51,7 @@ public class ScriptLinkedItem extends ScriptCustomizableItem implements IItemLin } @Override - public INpcScriptHandler getScriptHandler() { + public IScriptHandler getScriptHandler() { if (this.getLinkedItem() == null) return null; return this.getLinkedItem().getScriptHandler(); From cc0959dcfe8db467c4880dcc4640ee8fe75aa366 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Wed, 14 Jan 2026 00:16:58 +0200 Subject: [PATCH 18/19] Added run(EnumScriptType, Event) and run(String, Event) methods to IScriptUnit interface, with JaninoScript delegating to callByHookType(). This provides a cleaner abstraction that supports both ScriptContainer and JaninoScript without type checking. Affected files: - IScriptUnit: Added run() methods to interface - JaninoScript: Implemented run() delegation methods - DataScript, PlayerDataScript, GlobalNPCDataScript, ForgeDataScript - EffectScript, LinkedItemScript, RecipeScript - ScriptCustomItem, TileScripted: Refactored to use polymorphic calls --- .../npcs/blocks/tiles/TileScripted.java | 5 +- .../npcs/controllers/data/DataScript.java | 4 +- .../npcs/controllers/data/EffectScript.java | 6 +- .../controllers/data/ForgeDataScript.java | 9 +- .../controllers/data/GlobalNPCDataScript.java | 9 +- .../npcs/controllers/data/IScriptUnit.java | 25 +++++- .../controllers/data/LinkedItemScript.java | 6 +- .../controllers/data/PlayerDataScript.java | 26 +++--- .../npcs/controllers/data/RecipeScript.java | 6 +- .../java/noppes/npcs/janino/JaninoScript.java | 85 ++++++++++++++++++- .../java/noppes/npcs/janino/ScriptHook.java | 22 +++++ .../npcs/scripted/item/ScriptCustomItem.java | 5 +- 12 files changed, 156 insertions(+), 52 deletions(-) create mode 100644 src/main/java/noppes/npcs/janino/ScriptHook.java diff --git a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java index 2ecdb518e..7174bac6e 100644 --- a/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java +++ b/src/main/java/noppes/npcs/blocks/tiles/TileScripted.java @@ -25,7 +25,6 @@ import noppes.npcs.api.IBlock; import noppes.npcs.api.block.ITextPlane; import noppes.npcs.client.renderer.blocks.BlockScriptedRenderer; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptBlockHandler; import noppes.npcs.controllers.data.IScriptUnit; @@ -369,9 +368,7 @@ public class TileScripted extends TileEntity implements IScriptBlockHandler { } for (IScriptUnit script : scripts) { - if (script instanceof ScriptContainer) { - ((ScriptContainer) script).run(type, event); - } + script.run(type, event); } } diff --git a/src/main/java/noppes/npcs/controllers/data/DataScript.java b/src/main/java/noppes/npcs/controllers/data/DataScript.java index 71921e60b..014959919 100644 --- a/src/main/java/noppes/npcs/controllers/data/DataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/DataScript.java @@ -153,9 +153,7 @@ public class DataScript implements IScriptHandler { } for (IScriptUnit script : this.eventScripts) { - if (script instanceof ScriptContainer) { - ((ScriptContainer) script).run(type, event); - } + script.run(type, event); } ScriptContainer script = scripts.get(type); diff --git a/src/main/java/noppes/npcs/controllers/data/EffectScript.java b/src/main/java/noppes/npcs/controllers/data/EffectScript.java index 5ca67697d..dcd497fc8 100644 --- a/src/main/java/noppes/npcs/controllers/data/EffectScript.java +++ b/src/main/java/noppes/npcs/controllers/data/EffectScript.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.Constants; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.scripted.event.player.PlayerEvent; @@ -62,8 +61,9 @@ public class EffectScript implements IScriptHandler { if (!this.isEnabled()) { return; } - if (container instanceof ScriptContainer) - ((ScriptContainer) container).run(s, event); + if (container != null) { + container.run(s, event); + } } @Override diff --git a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java index 66563bf54..043e56efe 100644 --- a/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/ForgeDataScript.java @@ -78,14 +78,9 @@ public class ForgeDataScript implements IScriptHandler { } for (IScriptUnit script : this.scripts) { - if (script == null || !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - if (container.errored) - continue; - container.run(type, event); - } + script.run(type, event); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java index 4bbb742ce..c4dc15913 100644 --- a/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/GlobalNPCDataScript.java @@ -94,14 +94,9 @@ public class GlobalNPCDataScript implements IScriptHandler { } for (IScriptUnit script : this.scripts) { - if (script == null || !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - if (container.errored) - continue; - container.run(hookName, event); - } + script.run(hookName, event); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java index fcd3fc6f8..392901ede 100644 --- a/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java +++ b/src/main/java/noppes/npcs/controllers/data/IScriptUnit.java @@ -1,8 +1,9 @@ package noppes.npcs.controllers.data; +import cpw.mods.fml.common.eventhandler.Event; import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptContainer; -import noppes.npcs.janino.JaninoScript; import java.util.List; import java.util.Map; @@ -149,4 +150,26 @@ public interface IScriptUnit { * Set the error state of this script unit. */ void setErrored(boolean errored); + + // ==================== EXECUTION ==================== + + /** + * Execute this script unit for the given hook type and event. + * For ScriptContainer: calls run(EnumScriptType, Event) + * For JaninoScript: calls callByHookType(EnumScriptType, Event) + * + * @param type The script hook type + * @param event The event object + */ + void run(EnumScriptType type, Event event); + + /** + * Execute this script unit for the given hook name and event. + * For ScriptContainer: calls run(String, Event) + * For JaninoScript: converts hookName to EnumScriptType and calls callByHookType + * + * @param hookName The hook name (e.g., "init", "interact") + * @param event The event object + */ + void run(String hookName, Object event); } diff --git a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java index d13e64c50..a2f3a3025 100644 --- a/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java +++ b/src/main/java/noppes/npcs/controllers/data/LinkedItemScript.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.Constants; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import java.io.IOException; @@ -56,8 +55,9 @@ public class LinkedItemScript implements IScriptHandler { if (!this.isEnabled()) { return; } - if (container instanceof ScriptContainer) - ((ScriptContainer) container).run(s, event); + if (container != null) { + container.run(s, event); + } } @Override diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java index 7fd2eb644..c8dd007f7 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java @@ -121,18 +121,15 @@ public class PlayerDataScript implements IScriptHandler { IScriptUnit script = scripts.get(i); if (errored.contains(i)) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - container.run(hookName, event); - if (container.errored) { - errored.add(i); - } - for (Entry entry : container.console.entrySet()) { - if (!console.containsKey(entry.getKey())) - console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + entry.getValue()); - } - container.console.clear(); + script.run(hookName, event); + if (script.hasErrored()) { + errored.add(i); } + for (Entry entry : script.getConsole().entrySet()) { + if (!console.containsKey(entry.getKey())) + console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + entry.getValue()); + } + script.clearConsole(); } } else { if (ScriptController.Instance.lastLoaded > this.lastInited || ScriptController.Instance.lastPlayerUpdate > this.lastPlayerUpdate) { @@ -151,12 +148,9 @@ public class PlayerDataScript implements IScriptHandler { } for (IScriptUnit script : this.scripts) { - if (script == null || script.hasErrored()|| !script.hasCode()) + if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ScriptContainer container = (ScriptContainer) script; - container.run(hookName, event); - } + script.run(hookName, event); } } } diff --git a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java index ff9f681ad..ee1b32c08 100644 --- a/src/main/java/noppes/npcs/controllers/data/RecipeScript.java +++ b/src/main/java/noppes/npcs/controllers/data/RecipeScript.java @@ -8,7 +8,6 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.common.util.Constants; import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import java.io.IOException; @@ -53,8 +52,9 @@ public class RecipeScript implements IScriptHandler { public void callScript(String s, Event event) { if (!this.isEnabled()) return; - if (container instanceof ScriptContainer) - ((ScriptContainer) container).run(s, event); + if (container != null) { + container.run(s, event); + } } @Override diff --git a/src/main/java/noppes/npcs/janino/JaninoScript.java b/src/main/java/noppes/npcs/janino/JaninoScript.java index 13a7a33c9..a5e1f3274 100644 --- a/src/main/java/noppes/npcs/janino/JaninoScript.java +++ b/src/main/java/noppes/npcs/janino/JaninoScript.java @@ -1,12 +1,14 @@ package noppes.npcs.janino; import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.Event; import io.github.somehussar.janinoloader.api.script.IScriptBodyBuilder; import io.github.somehussar.janinoloader.api.script.IScriptClassBody; import net.minecraft.nbt.NBTTagCompound; import noppes.npcs.CustomNpcs; import noppes.npcs.NBTTags; import noppes.npcs.config.ConfigScript; +import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptUnit; import org.codehaus.commons.compiler.InternalCompilerException; @@ -51,6 +53,8 @@ public abstract class JaninoScript implements IScriptUnit { private List hookList = new ArrayList<>(); // Map from display name (with parameters if overloaded) to Method private Map hookMap = new HashMap<>(); + // Map from EnumScriptType to Method for OLD tab-based script system + private Map hookTypeMap = new HashMap<>(); protected JaninoScript(Class type, Consumer> buildSettings) { this.type = type; @@ -63,6 +67,9 @@ public abstract class JaninoScript implements IScriptUnit { sandbox = new Sandbox(permissions); this.scriptBody = builder.build(); + + // Build hook type map from @ScriptHook annotations + initializeHookTypeMap(); } protected T getUnsafe() { @@ -195,9 +202,85 @@ public abstract class JaninoScript implements IScriptUnit { sb.append(code).append("\n"); } } - + + /** + * Scans the Functions interface for @ScriptHook annotations and builds the hookTypeMap. + * This allows direct method invocation by EnumScriptType without switch statements. + */ + private void initializeHookTypeMap() { + for (Method method : type.getDeclaredMethods()) { + ScriptHook annotation = method.getAnnotation(ScriptHook.class); + if (annotation != null) { + for (EnumScriptType hookType : annotation.value()) { + hookTypeMap.put(hookType, method); + } + } + } + } + + /** + * Call a hook method by its EnumScriptType. + * Used by the OLD tab-based script system to execute hooks directly. + * + * @param hookType The script type/hook to execute + * @param event The event object to pass to the hook method + */ + public void callByHookType(EnumScriptType hookType, Object event) { + Method method = hookTypeMap.get(hookType); + if (method == null) { + // Hook not implemented or not annotated + return; + } + + ensureCompiled(); + T t = getUnsafe(); + if (t == null) + return; + + try { + sandbox.confine((PrivilegedAction) () -> { + try { + method.invoke(t, event); + } catch (Exception e) { + appendConsole("Error calling hook " + hookType.name() + ": " + e.getMessage()); + } + return null; + }); + } catch (Exception e) { + appendConsole("Runtime Error in hook " + hookType.name() + ": " + e.getMessage()); + } + } + // ==================== IScriptUnit IMPLEMENTATION ==================== + /** + * Execute this script unit for the given hook type and event. + * Implementation of IScriptUnit.run(EnumScriptType, Event) + * + * @param type The script hook type + * @param event The event object + */ + @Override + public void run(EnumScriptType type, Event event) { + callByHookType(type, event); + } + + /** + * Execute this script unit for the given hook name and event. + * Implementation of IScriptUnit.run(String, Event) + * + * @param hookName The hook name (e.g., "init", "interact") + * @param event The event object + */ + @Override + public void run(String hookName, Object event) { + try { + EnumScriptType enumType = EnumScriptType.valueOfIgnoreCase(hookName); + callByHookType(enumType, event); + } catch (IllegalArgumentException ignored) { + // Hook name doesn't map to an EnumScriptType + } + } @Override public String getScript() { return this.script; diff --git a/src/main/java/noppes/npcs/janino/ScriptHook.java b/src/main/java/noppes/npcs/janino/ScriptHook.java new file mode 100644 index 000000000..1b1ba598b --- /dev/null +++ b/src/main/java/noppes/npcs/janino/ScriptHook.java @@ -0,0 +1,22 @@ +package noppes.npcs.janino; + +import noppes.npcs.constants.EnumScriptType; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation to mark script hook methods and associate them with their EnumScriptType. + * Used by JaninoScript to automatically build a map of hook types to methods. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface ScriptHook { + /** + * The script type(s) this method handles. + * Multiple types can be specified for methods that handle multiple hooks. + */ + EnumScriptType[] value(); +} diff --git a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java index 87d233540..02f27b71c 100644 --- a/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java +++ b/src/main/java/noppes/npcs/scripted/item/ScriptCustomItem.java @@ -8,7 +8,6 @@ import noppes.npcs.NBTTags; import noppes.npcs.api.item.IItemCustom; import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.data.IScriptUnit; -import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptHandler; import noppes.npcs.scripted.CustomNPCsException; @@ -101,9 +100,7 @@ public class ScriptCustomItem extends ScriptCustomizableItem implements IItemCus if (script == null || script.hasErrored() || !script.hasCode()) continue; - if (script instanceof ScriptContainer) { - ((ScriptContainer) script).run(hookName, event); - } + script.run(hookName, event); if (script.hasErrored()) { this.errored.add(i); From 54d0fe2b1b73a37d5df6e200e023f7d857f6e997 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Wed, 14 Jan 2026 00:24:38 +0200 Subject: [PATCH 19/19] Very first implementation of JaninoNpcScript --- .../npcs/controllers/data/DataScript.java | 5 + .../java/noppes/npcs/janino/JaninoScript.java | 2 + .../npcs/janino/annotations/ParamName.java | 20 +++ .../janino/{ => annotations}/ScriptHook.java | 2 +- .../npcs/janino/impl/JaninoNpcScript.java | 120 ++++++++++++++++++ 5 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/main/java/noppes/npcs/janino/annotations/ParamName.java rename src/main/java/noppes/npcs/janino/{ => annotations}/ScriptHook.java (94%) create mode 100644 src/main/java/noppes/npcs/janino/impl/JaninoNpcScript.java diff --git a/src/main/java/noppes/npcs/controllers/data/DataScript.java b/src/main/java/noppes/npcs/controllers/data/DataScript.java index 014959919..6e07223a8 100644 --- a/src/main/java/noppes/npcs/controllers/data/DataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/DataScript.java @@ -19,6 +19,7 @@ import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptContainer; import noppes.npcs.controllers.ScriptController; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.janino.impl.JaninoNpcScript; import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.ScriptWorld; import noppes.npcs.scripted.constants.EntityType; @@ -312,4 +313,8 @@ public class DataScript implements IScriptHandler { public Collection getNPCScripts() { return this.scripts.values(); } + @Override + public IScriptUnit createJaninoScriptUnit() { + return new JaninoNpcScript(); + } } diff --git a/src/main/java/noppes/npcs/janino/JaninoScript.java b/src/main/java/noppes/npcs/janino/JaninoScript.java index a5e1f3274..0f9d5c9f1 100644 --- a/src/main/java/noppes/npcs/janino/JaninoScript.java +++ b/src/main/java/noppes/npcs/janino/JaninoScript.java @@ -11,6 +11,8 @@ import noppes.npcs.config.ConfigScript; import noppes.npcs.constants.EnumScriptType; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.IScriptUnit; +import noppes.npcs.janino.annotations.ParamName; +import noppes.npcs.janino.annotations.ScriptHook; import org.codehaus.commons.compiler.InternalCompilerException; import org.codehaus.commons.compiler.Sandbox; diff --git a/src/main/java/noppes/npcs/janino/annotations/ParamName.java b/src/main/java/noppes/npcs/janino/annotations/ParamName.java new file mode 100644 index 000000000..6b1e9ec25 --- /dev/null +++ b/src/main/java/noppes/npcs/janino/annotations/ParamName.java @@ -0,0 +1,20 @@ +package noppes.npcs.janino.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Specifies the parameter name and type to use when generating method stubs. + * Applied to interface method parameters to preserve their names and types in generated code. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.PARAMETER) +public @interface ParamName { + /** The parameter name (e.g., "event") */ + String value(); + + /** The fully qualified type name (e.g., "noppes.npcs.api.event.INpcEvent.InitEvent") */ + String type() default ""; +} diff --git a/src/main/java/noppes/npcs/janino/ScriptHook.java b/src/main/java/noppes/npcs/janino/annotations/ScriptHook.java similarity index 94% rename from src/main/java/noppes/npcs/janino/ScriptHook.java rename to src/main/java/noppes/npcs/janino/annotations/ScriptHook.java index 1b1ba598b..d4720b5d8 100644 --- a/src/main/java/noppes/npcs/janino/ScriptHook.java +++ b/src/main/java/noppes/npcs/janino/annotations/ScriptHook.java @@ -1,4 +1,4 @@ -package noppes.npcs.janino; +package noppes.npcs.janino.annotations; import noppes.npcs.constants.EnumScriptType; diff --git a/src/main/java/noppes/npcs/janino/impl/JaninoNpcScript.java b/src/main/java/noppes/npcs/janino/impl/JaninoNpcScript.java new file mode 100644 index 000000000..b41e2aac8 --- /dev/null +++ b/src/main/java/noppes/npcs/janino/impl/JaninoNpcScript.java @@ -0,0 +1,120 @@ +package noppes.npcs.janino.impl; + +import noppes.npcs.api.event.IAbilityEvent; +import noppes.npcs.api.event.INpcEvent; +import noppes.npcs.api.event.IProjectileEvent; +import noppes.npcs.constants.EnumScriptType; +import noppes.npcs.janino.JaninoScript; +import noppes.npcs.janino.annotations.ParamName; +import noppes.npcs.janino.annotations.ScriptHook; + +/** + * Janino (Java) script implementation for NPC events. + * This allows NPCs to use compiled Java code instead of ECMAScript. + */ +public class JaninoNpcScript extends JaninoScript { + + public JaninoNpcScript() { + super(Functions.class, (builder) -> builder + .setDefaultImports( + "noppes.npcs.api.*", + "noppes.npcs.api.entity.*", + "noppes.npcs.api.event.*", + "noppes.npcs.api.handler.*", + "noppes.npcs.api.handler.data.*", + "noppes.npcs.api.item.*", + "noppes.npcs.api.ability.*" + ) + ); + } + + /** + * Interface defining the hook methods available for NPC scripts. + * Each method corresponds to an NPC event from ScriptHookController CONTEXT_NPC. + * Methods are annotated with @ScriptHook to map them to their EnumScriptType. + */ + public interface Functions { + // Core lifecycle events + @ScriptHook(EnumScriptType.INIT) + default void init(@ParamName("event") INpcEvent.InitEvent event) {} + + @ScriptHook(EnumScriptType.TICK) + default void tick(@ParamName("event") INpcEvent.UpdateEvent event) {} + + + // Interaction events + @ScriptHook(EnumScriptType.INTERACT) + default void interact(@ParamName("event") INpcEvent.InteractEvent event) {} + + @ScriptHook(EnumScriptType.DIALOG) + default void dialog(@ParamName("event") INpcEvent.DialogEvent event) {} + + @ScriptHook(EnumScriptType.DIALOG_CLOSE) + default void dialogClose(@ParamName("event") INpcEvent.DialogClosedEvent event) {} + + + // Combat events - damage + @ScriptHook(EnumScriptType.DAMAGED) + default void damaged(@ParamName("event") INpcEvent.DamagedEvent event) {} + + @ScriptHook(EnumScriptType.KILLED) + default void killed(@ParamName("event") INpcEvent.DiedEvent event) {} + + @ScriptHook(EnumScriptType.KILLS) + default void kills(@ParamName("event") INpcEvent.KilledEntityEvent event) {} + + + // Combat events - attacks + @ScriptHook(EnumScriptType.ATTACK_MELEE) + default void meleeAttack(@ParamName("event") INpcEvent.MeleeAttackEvent event) {} + + @ScriptHook(EnumScriptType.ATTACK_SWING) + default void meleeSwing(@ParamName("event") INpcEvent.SwingEvent event) {} + + @ScriptHook(EnumScriptType.RANGED_LAUNCHED) + default void rangedLaunched(@ParamName("event") INpcEvent.RangedLaunchedEvent event) {} + + + // Targeting events + @ScriptHook(EnumScriptType.TARGET) + default void target(@ParamName("event") INpcEvent.TargetEvent event) {} + + @ScriptHook(EnumScriptType.TARGET_LOST) + default void targetLost(@ParamName("event") INpcEvent.TargetLostEvent event) {} + + // Other NPC events + @ScriptHook(EnumScriptType.COLLIDE) + default void collide(@ParamName("event") INpcEvent.CollideEvent event) {} + + @ScriptHook(EnumScriptType.TIMER) + default void timer(@ParamName("event") INpcEvent.TimerEvent event) {} + + + // Projectile events + @ScriptHook(EnumScriptType.PROJECTILE_TICK) + default void projectileTick(@ParamName("event") IProjectileEvent.UpdateEvent event) {} + + @ScriptHook(EnumScriptType.PROJECTILE_IMPACT) + default void projectileImpact(@ParamName("event") IProjectileEvent.ImpactEvent event) {} + + + // Ability events + @ScriptHook(EnumScriptType.ABILITY_START) + default void abilityStart(@ParamName("event") IAbilityEvent.StartEvent event) {} + + @ScriptHook(EnumScriptType.ABILITY_EXECUTE) + default void abilityExecute(@ParamName("event") IAbilityEvent.ExecuteEvent event) {} + + @ScriptHook(EnumScriptType.ABILITY_HIT) + default void abilityHit(@ParamName("event") IAbilityEvent.HitEvent event) {} + + @ScriptHook(EnumScriptType.ABILITY_TICK) + default void abilityTick(@ParamName("event") IAbilityEvent.TickEvent event) {} + + @ScriptHook(EnumScriptType.ABILITY_INTERRUPT) + default void abilityInterrupt(@ParamName("event") IAbilityEvent.InterruptEvent event) {} + + @ScriptHook(EnumScriptType.ABILITY_COMPLETE) + default void abilityComplete(@ParamName("event") IAbilityEvent.CompleteEvent event) {} + } +}