From f8dc8d9268dfab3efd726a2fe21a1f9f204d5a96 Mon Sep 17 00:00:00 2001 From: somehussar <148253652+somehussar@users.noreply.github.com> Date: Tue, 9 Dec 2025 08:11:34 +0100 Subject: [PATCH] Basic NPC Wrapper --- src/main/java/noppes/npcs/EventHooks.java | 41 ++++++++- .../npcs/controllers/ScriptController.java | 6 ++ .../npcs/entity/EntityNPCInterface.java | 2 + .../janino/EntityUnloadListener.java | 77 +++++++++++++++++ .../wrapper/AbstractNPCJavaHandler.java | 60 +++++++++++++ .../somehussar/janino/wrapper/NPCWrapper.java | 84 +++++++++++++++++++ 6 files changed, 267 insertions(+), 3 deletions(-) create mode 100644 src/main/java/somehussar/janino/EntityUnloadListener.java create mode 100644 src/main/java/somehussar/janino/wrapper/AbstractNPCJavaHandler.java create mode 100644 src/main/java/somehussar/janino/wrapper/NPCWrapper.java diff --git a/src/main/java/noppes/npcs/EventHooks.java b/src/main/java/noppes/npcs/EventHooks.java index 9cb5b1669..ebb3933a1 100644 --- a/src/main/java/noppes/npcs/EventHooks.java +++ b/src/main/java/noppes/npcs/EventHooks.java @@ -266,6 +266,8 @@ public class EventHooks { noppes.npcs.scripted.event.NpcEvent.InitEvent event = new noppes.npcs.scripted.event.NpcEvent.InitEvent(npc.wrappedNPC); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.INIT, event); npc.script.callScript(EnumScriptType.INIT, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onInitialize(event); NpcAPI.EVENT_BUS.post(event); npc.advanced.soulStoneInit = false; } @@ -277,6 +279,8 @@ public class EventHooks { noppes.npcs.scripted.event.NpcEvent.UpdateEvent event = new noppes.npcs.scripted.event.NpcEvent.UpdateEvent(npc.wrappedNPC); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.TICK, event); npc.script.callScript(EnumScriptType.TICK, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onUpdate(event); NpcAPI.EVENT_BUS.post(event); } @@ -287,6 +291,8 @@ public class EventHooks { NpcEvent.DialogEvent event = new NpcEvent.DialogEvent(npc.wrappedNPC, player, dialogId, optionId, dialog); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.DIALOG, event); npc.script.callScript(EnumScriptType.DIALOG, event, "player", event.getPlayer(), "dialog", event.getDialogId(), "option", event.getOptionId(), "dialogObj", event.getDialog()); + if (npc.janinoHandler != null) + npc.janinoHandler.onDialog(event); return NpcAPI.EVENT_BUS.post(event); } @@ -298,7 +304,8 @@ public class EventHooks { NpcEvent.DialogClosedEvent event = new NpcEvent.DialogClosedEvent(npc.wrappedNPC, player, dialogId, optionId, dialog); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.DIALOG_CLOSE, event); npc.script.callScript(EnumScriptType.DIALOG_CLOSE, event, "player", event.getPlayer(), "dialog", event.getDialogId(), "option", event.getOptionId(), "dialogObj", event.getDialog()); - + if (npc.janinoHandler != null) + npc.janinoHandler.onDialogClosed(event); NpcAPI.EVENT_BUS.post(event); } @@ -320,6 +327,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ATTACK_MELEE, event); npc.script.callScript(EnumScriptType.ATTACK_MELEE, event, "target", event.target); npc.script.callScript(EnumScriptType.ATTACK, event, "target", event.target); + if (npc.janinoHandler != null) + npc.janinoHandler.onAttack(event); return NpcAPI.EVENT_BUS.post(event); } @@ -329,6 +338,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.ATTACK_SWING, event); npc.script.callScript(EnumScriptType.ATTACK_SWING, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onMeleeSwing(event); return NpcAPI.EVENT_BUS.post(event); } @@ -339,6 +350,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.RANGED_LAUNCHED, event); npc.script.callScript(EnumScriptType.RANGED_LAUNCHED, event, "target", event.target); npc.script.callScript(EnumScriptType.ATTACK, event, "target", event.target); + if (npc.janinoHandler != null) + npc.janinoHandler.onRangedAttack(event); return NpcAPI.EVENT_BUS.post(event); } @@ -349,6 +362,8 @@ public class EventHooks { NpcEvent.KilledEntityEvent event = new NpcEvent.KilledEntityEvent(npc.wrappedNPC, entity); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.KILLS, event); npc.script.callScript(EnumScriptType.KILLS, event, "target", entity); + if (npc.janinoHandler != null) + npc.janinoHandler.onKillEntity(event); NpcAPI.EVENT_BUS.post(event); } @@ -358,6 +373,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.TARGET, event); npc.script.callScript(EnumScriptType.TARGET, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onTarget(event); return NpcAPI.EVENT_BUS.post(event); } @@ -368,6 +385,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.TARGET_LOST, event); npc.script.callScript(EnumScriptType.TARGET_LOST, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onTargetLost(event); return NpcAPI.EVENT_BUS.post(event); } @@ -378,6 +397,8 @@ public class EventHooks { NpcEvent.CollideEvent event = new NpcEvent.CollideEvent(npc.wrappedNPC, entity); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.COLLIDE, event); npc.script.callScript(EnumScriptType.COLLIDE, event, "entity", entity); + if (npc.janinoHandler != null) + npc.janinoHandler.onCollide(event); NpcAPI.EVENT_BUS.post(event); } @@ -387,6 +408,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.DAMAGED, event); npc.script.callScript(EnumScriptType.DAMAGED, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onDamaged(event); return NpcAPI.EVENT_BUS.post(event); } @@ -396,6 +419,8 @@ public class EventHooks { ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.KILLED, event); npc.script.callScript(EnumScriptType.KILLED, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onNPCKilled(event); return NpcAPI.EVENT_BUS.post(event); } @@ -406,6 +431,8 @@ public class EventHooks { NpcEvent.TimerEvent event = new NpcEvent.TimerEvent(npc.wrappedNPC, id); ScriptController.Instance.globalNpcScripts.callScript(EnumScriptType.TIMER, event); npc.script.callScript(EnumScriptType.TIMER, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onTimer(event); NpcAPI.EVENT_BUS.post(event); } @@ -421,7 +448,11 @@ public class EventHooks { EntityLivingBase thrower = projectile.getThrower(); if (thrower != null) { if (thrower instanceof EntityNPCInterface) { - ((EntityNPCInterface) thrower).script.callScript(EnumScriptType.PROJECTILE_TICK, event); + EntityNPCInterface npc = (EntityNPCInterface) thrower; + + npc.script.callScript(EnumScriptType.PROJECTILE_TICK, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onProjectileTick(event); } } @@ -439,7 +470,11 @@ public class EventHooks { EntityLivingBase thrower = projectile.getThrower(); if (thrower != null) { if (thrower instanceof EntityNPCInterface) { - ((EntityNPCInterface) thrower).script.callScript(EnumScriptType.PROJECTILE_IMPACT, event); + EntityNPCInterface npc = (EntityNPCInterface) thrower; + + npc.script.callScript(EnumScriptType.PROJECTILE_IMPACT, event); + if (npc.janinoHandler != null) + npc.janinoHandler.onProjectileImpact(event); } } diff --git a/src/main/java/noppes/npcs/controllers/ScriptController.java b/src/main/java/noppes/npcs/controllers/ScriptController.java index d4246440b..6fb4406c2 100644 --- a/src/main/java/noppes/npcs/controllers/ScriptController.java +++ b/src/main/java/noppes/npcs/controllers/ScriptController.java @@ -21,6 +21,7 @@ import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.ScriptWorld; import noppes.npcs.util.JsonException; import noppes.npcs.util.NBTJsonUtil; +import somehussar.janino.EntityUnloadListener; import javax.script.ScriptContext; import javax.script.ScriptEngine; @@ -361,6 +362,11 @@ public class ScriptController { return list; } + @SubscribeEvent + public void addWorldAccess(WorldEvent.Load event) { + event.world.addWorldAccess(new EntityUnloadListener()); + } + @SubscribeEvent public void invoke(WorldEvent.Save event) { if (!shouldSave || event.world.isRemote || event.world != MinecraftServer.getServer().worldServers[0]) diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index c72aa7117..ddb090142 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -157,6 +157,7 @@ import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.entity.ScriptNpc; import noppes.npcs.scripted.event.NpcEvent; import noppes.npcs.util.GameProfileAlt; +import somehussar.janino.wrapper.NPCWrapper; import java.io.IOException; import java.util.ArrayList; @@ -188,6 +189,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti public float baseHeight = 1.8f; public float scaleX, scaleY, scaleZ; + public NPCWrapper janinoHandler; private boolean wasKilled = false; public RoleInterface roleInterface; public JobInterface jobInterface; diff --git a/src/main/java/somehussar/janino/EntityUnloadListener.java b/src/main/java/somehussar/janino/EntityUnloadListener.java new file mode 100644 index 000000000..afcbec5b8 --- /dev/null +++ b/src/main/java/somehussar/janino/EntityUnloadListener.java @@ -0,0 +1,77 @@ +package somehussar.janino; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.IWorldAccess; +import noppes.npcs.entity.EntityNPCInterface; + +public class EntityUnloadListener implements IWorldAccess { + @Override + public void markBlockForUpdate(int p_147586_1_, int p_147586_2_, int p_147586_3_) { + + } + + @Override + public void markBlockForRenderUpdate(int p_147588_1_, int p_147588_2_, int p_147588_3_) { + + } + + @Override + public void markBlockRangeForRenderUpdate(int p_147585_1_, int p_147585_2_, int p_147585_3_, int p_147585_4_, int p_147585_5_, int p_147585_6_) { + + } + + @Override + public void playSound(String soundName, double x, double y, double z, float volume, float pitch) { + + } + + @Override + public void playSoundToNearExcept(EntityPlayer p_85102_1_, String p_85102_2_, double p_85102_3_, double p_85102_5_, double p_85102_7_, float p_85102_9_, float p_85102_10_) { + + } + + @Override + public void spawnParticle(String p_72708_1_, double p_72708_2_, double p_72708_4_, double p_72708_6_, double p_72708_8_, double p_72708_10_, double p_72708_12_) { + + } + + @Override + public void onEntityCreate(Entity p_72703_1_) { + + } + + @Override + public void onEntityDestroy(Entity entity) { + if (entity instanceof EntityNPCInterface) { + EntityNPCInterface npc = (EntityNPCInterface) entity; + if (npc.janinoHandler != null) + npc.janinoHandler.prepareToUnload(); + } + } + + @Override + public void playRecord(String p_72702_1_, int p_72702_2_, int p_72702_3_, int p_72702_4_) { + + } + + @Override + public void broadcastSound(int p_82746_1_, int p_82746_2_, int p_82746_3_, int p_82746_4_, int p_82746_5_) { + + } + + @Override + public void playAuxSFX(EntityPlayer p_72706_1_, int p_72706_2_, int p_72706_3_, int p_72706_4_, int p_72706_5_, int p_72706_6_) { + + } + + @Override + public void destroyBlockPartially(int p_147587_1_, int p_147587_2_, int p_147587_3_, int p_147587_4_, int p_147587_5_) { + + } + + @Override + public void onStaticEntitiesChanged() { + + } +} diff --git a/src/main/java/somehussar/janino/wrapper/AbstractNPCJavaHandler.java b/src/main/java/somehussar/janino/wrapper/AbstractNPCJavaHandler.java new file mode 100644 index 000000000..37441c070 --- /dev/null +++ b/src/main/java/somehussar/janino/wrapper/AbstractNPCJavaHandler.java @@ -0,0 +1,60 @@ +package somehussar.janino.wrapper; + +import io.github.somehussar.janinoloader.annotations.PermissableScriptHandler; +import noppes.npcs.api.event.INpcEvent; +import noppes.npcs.scripted.event.NpcEvent; +import noppes.npcs.scripted.event.ProjectileEvent; + +public abstract class AbstractNPCJavaHandler { + + public void prepareToUnload() { + } + + public void onInitialize(INpcEvent.InitEvent event) { + } + + public void onUpdate(NpcEvent.UpdateEvent event) { + } + + public void onDialog(NpcEvent.DialogEvent event) { + } + + public void onProjectileTick(ProjectileEvent.UpdateEvent event) { + } + + public void onDialogClosed(NpcEvent.DialogClosedEvent event) { + } + + public void onAttack(NpcEvent.MeleeAttackEvent event) { + } + + public void onRangedAttack(NpcEvent.RangedLaunchedEvent event) { + } + + public void onMeleeSwing(NpcEvent.SwingEvent event) { + } + + public void onKillEntity(NpcEvent.KilledEntityEvent event) { + } + + public void onTarget(NpcEvent.TargetEvent event) { + } + + public void onTargetLost(NpcEvent.TargetLostEvent event) { + } + + public void onCollide(NpcEvent.CollideEvent event) { + } + + public void onDamaged(NpcEvent.DamagedEvent event) { + } + + public void onNPCKilled(NpcEvent.DiedEvent event) { + } + + public void onTimer(NpcEvent.TimerEvent event) { + } + + public void onProjectileImpact(ProjectileEvent.ImpactEvent event) { + } +} diff --git a/src/main/java/somehussar/janino/wrapper/NPCWrapper.java b/src/main/java/somehussar/janino/wrapper/NPCWrapper.java new file mode 100644 index 000000000..710f89734 --- /dev/null +++ b/src/main/java/somehussar/janino/wrapper/NPCWrapper.java @@ -0,0 +1,84 @@ +package somehussar.janino.wrapper; + +import io.github.somehussar.janinoloader.api.script.IScriptClassBody; +import org.codehaus.commons.compiler.Sandbox; + +public final class NPCWrapper { + + private final Sandbox sandbox; + private final IScriptClassBody scriptBody; + + public NPCWrapper(Sandbox sandbox, IScriptClassBody scriptBody) { + this.sandbox = sandbox; + this.scriptBody = scriptBody; + } + + public void prepareToUnload() { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().prepareToUnload(); return null; }); + } + + public void onInitialize(noppes.npcs.api.event.INpcEvent.InitEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onInitialize(event); return null; }); + } + + public void onUpdate(noppes.npcs.scripted.event.NpcEvent.UpdateEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onUpdate(event); return null; }); + } + + public void onDialog(noppes.npcs.scripted.event.NpcEvent.DialogEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onDialog(event); return null; }); + } + + public void onProjectileTick(noppes.npcs.scripted.event.ProjectileEvent.UpdateEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onProjectileTick(event); return null; }); + } + + public void onDialogClosed(noppes.npcs.scripted.event.NpcEvent.DialogClosedEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onDialogClosed(event); return null; }); + } + + public void onAttack(noppes.npcs.scripted.event.NpcEvent.MeleeAttackEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onAttack(event); return null; }); + } + + public void onRangedAttack(noppes.npcs.scripted.event.NpcEvent.RangedLaunchedEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onRangedAttack(event); return null; }); + } + + public void onMeleeSwing(noppes.npcs.scripted.event.NpcEvent.SwingEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onMeleeSwing(event); return null; }); + } + + public void onKillEntity(noppes.npcs.scripted.event.NpcEvent.KilledEntityEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onKillEntity(event); return null; }); + } + + public void onTarget(noppes.npcs.scripted.event.NpcEvent.TargetEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onTarget(event); return null; }); + } + + public void onTargetLost(noppes.npcs.scripted.event.NpcEvent.TargetLostEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onTargetLost(event); return null; }); + } + + public void onCollide(noppes.npcs.scripted.event.NpcEvent.CollideEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onCollide(event); return null; }); + } + + public void onDamaged(noppes.npcs.scripted.event.NpcEvent.DamagedEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onDamaged(event); return null; }); + } + + public void onNPCKilled(noppes.npcs.scripted.event.NpcEvent.DiedEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onNPCKilled(event); return null; }); + } + + public void onTimer(noppes.npcs.scripted.event.NpcEvent.TimerEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onTimer(event); return null; }); + } + + public void onProjectileImpact(noppes.npcs.scripted.event.ProjectileEvent.ImpactEvent event) { + sandbox.confine((java.security.PrivilegedAction) () -> { scriptBody.get().onProjectileImpact(event); return null; }); + } + +}