From 18ff2bff785f548d09a483e249042c4d8d4cb4ac Mon Sep 17 00:00:00 2001 From: "Luis C.M" Date: Wed, 23 Mar 2022 03:54:06 -0500 Subject: [PATCH] Implemented Global NPC Events! All NPCs activate these scripts. If a player wants to create a script that's universally used by all NPCs, this allows for that to happen with a lot of ease! --- src/main/java/noppes/npcs/CustomNpcs.java | 1 + src/main/java/noppes/npcs/DataScript.java | 1 + src/main/java/noppes/npcs/EventHooks.java | 97 +++++- .../java/noppes/npcs/NoppesUtilPlayer.java | 2 +- .../java/noppes/npcs/NoppesUtilServer.java | 2 +- .../java/noppes/npcs/PacketHandlerServer.java | 17 +- .../java/noppes/npcs/ServerEventsHandler.java | 2 +- .../client/gui/script/GuiScriptAllNPCs.java | 33 ++ .../client/gui/script/GuiScriptGlobal.java | 4 + .../client/gui/script/GuiScriptInterface.java | 17 + .../npcs/constants/EnumPacketServer.java | 3 + .../npcs/controllers/ScriptController.java | 38 +++ .../npcs/controllers/data/NPCDataScript.java | 298 ++++++++++++++++++ .../npcs/entity/EntityNPCInterface.java | 44 +-- .../noppes/npcs/scripted/event/NpcEvent.java | 41 ++- 15 files changed, 562 insertions(+), 38 deletions(-) create mode 100644 src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java create mode 100644 src/main/java/noppes/npcs/controllers/data/NPCDataScript.java diff --git a/src/main/java/noppes/npcs/CustomNpcs.java b/src/main/java/noppes/npcs/CustomNpcs.java index a5aaa037e..f5890f9a4 100644 --- a/src/main/java/noppes/npcs/CustomNpcs.java +++ b/src/main/java/noppes/npcs/CustomNpcs.java @@ -270,6 +270,7 @@ public class CustomNpcs { new LinkedNpcController(); ScriptController.Instance.loadStoredData(); ScriptController.Instance.loadForgeScripts(); + ScriptController.Instance.loadNPCScripts(); ScriptController.Instance.loadPlayerScripts(); ScriptController.HasStart = false; WrapperNpcAPI.clearCache(); diff --git a/src/main/java/noppes/npcs/DataScript.java b/src/main/java/noppes/npcs/DataScript.java index d4074bda2..90b435332 100644 --- a/src/main/java/noppes/npcs/DataScript.java +++ b/src/main/java/noppes/npcs/DataScript.java @@ -109,6 +109,7 @@ public class DataScript implements IScriptHandler { return false; if(!hasInited){ hasInited = true; + EventHooks.onNPCInit(this.npc); callScript(EnumScriptType.INIT); } ScriptContainer script = scripts.get(type.ordinal()); diff --git a/src/main/java/noppes/npcs/EventHooks.java b/src/main/java/noppes/npcs/EventHooks.java index c5e54cfc9..d7db62fb1 100644 --- a/src/main/java/noppes/npcs/EventHooks.java +++ b/src/main/java/noppes/npcs/EventHooks.java @@ -19,13 +19,13 @@ import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.event.entity.EntityEvent; import net.minecraftforge.event.world.WorldEvent; -import noppes.npcs.controllers.CustomGuiController; -import noppes.npcs.controllers.Quest; -import noppes.npcs.controllers.ScriptController; +import noppes.npcs.controllers.*; import noppes.npcs.controllers.data.ForgeDataScript; +import noppes.npcs.controllers.data.NPCDataScript; import noppes.npcs.controllers.data.PlayerDataScript; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.*; +import noppes.npcs.scripted.entity.ScriptNpc; import noppes.npcs.scripted.entity.ScriptPlayer; import noppes.npcs.scripted.event.*; import noppes.npcs.scripted.event.PlayerEvent.ChatEvent; @@ -42,7 +42,6 @@ import noppes.npcs.scripted.interfaces.IItemStack; import noppes.npcs.scripted.interfaces.IWorld; import noppes.npcs.scripted.wrapper.WrapperNpcAPI; import noppes.npcs.constants.EnumScriptType; -import noppes.npcs.controllers.PlayerData; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -51,12 +50,100 @@ public class EventHooks { public EventHooks() { } - + public static void onNPCInit(EntityNPCInterface npc) { + noppes.npcs.scripted.event.NpcEvent.InitEvent event = new noppes.npcs.scripted.event.NpcEvent.InitEvent(npc.wrappedNPC); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.INIT, event); + WrapperNpcAPI.EVENT_BUS.post(event); + } + + public static void onNPCUpdate(EntityNPCInterface npc) { + noppes.npcs.scripted.event.NpcEvent.UpdateEvent event = new noppes.npcs.scripted.event.NpcEvent.UpdateEvent(npc.wrappedNPC); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.TICK, event); + npc.script.callScript(EnumScriptType.TICK); + WrapperNpcAPI.EVENT_BUS.post(event); + } + + public static void onNPCDialog(EntityNPCInterface npc, EntityPlayer player, int id, Dialog dialog) { + NpcEvent.DialogEvent event = new NpcEvent.DialogEvent(npc.wrappedNPC, player, id, dialog); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.DIALOG, event); + npc.script.callScript(EnumScriptType.DIALOG, "event", new ScriptEventDialog(), "player", player, "dialog", dialog.id); + WrapperNpcAPI.EVENT_BUS.post(event); + } + + public static void onNPCDialogClosed(EntityNPCInterface npc, EntityPlayer player, int dialogId, int optionId, Dialog dialog) { + NpcEvent.DialogClosedEvent event = new NpcEvent.DialogClosedEvent(npc.wrappedNPC, player, dialogId, optionId, dialog); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.DIALOG_CLOSE, event); + npc.script.callScript(EnumScriptType.DIALOG_CLOSE, "player", player, "dialog", dialogId, "option", optionId + 1); + WrapperNpcAPI.EVENT_BUS.post(event); + } + + public static boolean onNPCInteract(EntityNPCInterface npc, EntityPlayer player) { + NpcEvent.InteractEvent event = new NpcEvent.InteractEvent(npc.wrappedNPC,player); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.INTERACT, event); + boolean result = npc.script.callScript(EnumScriptType.INTERACT, "player", player); + WrapperNpcAPI.EVENT_BUS.post(event); + return result; + } + + public static boolean onNPCMeleeAttack(EntityNPCInterface npc, float damage, EntityLivingBase target){ + NpcEvent.MeleeAttackEvent event = new NpcEvent.MeleeAttackEvent(npc.wrappedNPC,damage,target); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.ATTACK_MELEE, event); + boolean result = npc.script.callScript(EnumScriptType.ATTACK, "event", event, "target", target); + WrapperNpcAPI.EVENT_BUS.post(event); + return result; + } + + public static boolean onNPCRangedAttack(EntityNPCInterface npc, float damage, EntityLivingBase target){ + NpcEvent.RangedLaunchedEvent event = new NpcEvent.RangedLaunchedEvent(npc.wrappedNPC,damage,target); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.RANGED_LAUNCHED, event); + boolean result = npc.script.callScript(EnumScriptType.ATTACK, "event", event, "target", target); + WrapperNpcAPI.EVENT_BUS.post(event); + return result; + } + + public static void onNPCKilledEntity(EntityNPCInterface npc, EntityLivingBase entity){ + NpcEvent.KilledEntityEvent event = new NpcEvent.KilledEntityEvent(npc.wrappedNPC,entity); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.KILLS, event); + npc.script.callScript(EnumScriptType.KILLS, "target", entity); + WrapperNpcAPI.EVENT_BUS.post(event); + } + + public static boolean onNPCTarget(EntityNPCInterface npc, EntityLivingBase target){ + NpcEvent.TargetEvent event = new NpcEvent.TargetEvent(npc.wrappedNPC,target); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.TARGET, event); + boolean result = npc.script.callScript(EnumScriptType.TARGET, "event", event); + WrapperNpcAPI.EVENT_BUS.post(event); + return result; + } + + public static void onNPCCollide(EntityNPCInterface npc, Entity entity){ + NpcEvent.CollideEvent event = new NpcEvent.CollideEvent(npc.wrappedNPC,entity); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.COLLIDE, event); + npc.script.callScript(EnumScriptType.COLLIDE, "entity", entity); + WrapperNpcAPI.EVENT_BUS.post(event); + } + + public static boolean onNPCDamaged(EntityNPCInterface npc, Entity source, float damage, DamageSource damagesource, ScriptEventDamaged damagedEvent){ + NpcEvent.DamagedEvent event = new NpcEvent.DamagedEvent(npc.wrappedNPC,source,damage,damagesource); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.DAMAGED, event); + boolean result = npc.script.callScript(EnumScriptType.DAMAGED, "event", damagedEvent); + WrapperNpcAPI.EVENT_BUS.post(event); + return result; + } + + public static boolean onNPCKilled(EntityNPCInterface npc, DamageSource damagesource, Entity entity, ScriptEventKilled killedEvent){ + NpcEvent.DiedEvent event = new NpcEvent.DiedEvent(npc.wrappedNPC,damagesource,entity); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.KILLED, event); + boolean result = npc.script.callScript(EnumScriptType.KILLED, "event", killedEvent); + WrapperNpcAPI.EVENT_BUS.post(event); + return result; + } public static void onNPCTimer(EntityNPCInterface npc, int id) { NpcEvent.TimerEvent event = new NpcEvent.TimerEvent(npc.wrappedNPC, id); ScriptEventTimer scriptEvent = new ScriptEventTimer(id); npc.script.callScript(EnumScriptType.TIMER, "event", scriptEvent); + ScriptController.Instance.npcScripts.callScript(EnumScriptType.TIMER, event); WrapperNpcAPI.EVENT_BUS.post(event); } diff --git a/src/main/java/noppes/npcs/NoppesUtilPlayer.java b/src/main/java/noppes/npcs/NoppesUtilPlayer.java index db0bd623e..4d59f4c40 100644 --- a/src/main/java/noppes/npcs/NoppesUtilPlayer.java +++ b/src/main/java/noppes/npcs/NoppesUtilPlayer.java @@ -253,7 +253,7 @@ public class NoppesUtilPlayer { return; EventHooks.onDialogOption(new DialogEvent.DialogOption(new ScriptPlayer((EntityPlayerMP) player), dialog)); - npc.script.callScript(EnumScriptType.DIALOG_CLOSE, "player", player, "dialog", dialogId, "option", optionId + 1); + EventHooks.onNPCDialogClosed(npc,player,dialogId,optionId+1,dialog); if(!dialog.hasDialogs(player) && !dialog.hasOtherOptions()) { EventHooks.onDialogClosed(new DialogEvent.DialogClosed(new ScriptPlayer((EntityPlayerMP) player), dialog)); diff --git a/src/main/java/noppes/npcs/NoppesUtilServer.java b/src/main/java/noppes/npcs/NoppesUtilServer.java index 44c99b19c..40e2fccdd 100644 --- a/src/main/java/noppes/npcs/NoppesUtilServer.java +++ b/src/main/java/noppes/npcs/NoppesUtilServer.java @@ -203,7 +203,7 @@ public class NoppesUtilServer { if(!data.dialogsRead.contains(dialog.id)) data.dialogsRead.add(dialog.id); setEditingNpc(player, npc); - npc.script.callScript(EnumScriptType.DIALOG, "event", new ScriptEventDialog(), "player", player, "dialog", dialog.id); + EventHooks.onNPCDialog(npc, player, dialog.id, dialog); } public static void runCommand(EntityPlayer player, String name, String command){ runCommand(player, name, command, player); diff --git a/src/main/java/noppes/npcs/PacketHandlerServer.java b/src/main/java/noppes/npcs/PacketHandlerServer.java index d121009e9..8bc44438a 100644 --- a/src/main/java/noppes/npcs/PacketHandlerServer.java +++ b/src/main/java/noppes/npcs/PacketHandlerServer.java @@ -41,6 +41,7 @@ import noppes.npcs.containers.ContainerMail; import noppes.npcs.controllers.*; import noppes.npcs.controllers.LinkedNpcController.LinkedData; import noppes.npcs.controllers.data.ForgeDataScript; +import noppes.npcs.controllers.data.NPCDataScript; import noppes.npcs.controllers.data.PlayerDataScript; import noppes.npcs.entity.EntityCustomNpc; import noppes.npcs.entity.EntityNPCInterface; @@ -102,7 +103,7 @@ public class PacketHandlerServer{ else if(type.hasPermission() && !CustomNpcsPermissions.Instance.hasPermission(player, type.permission)){ //player doesnt have permission to do this } - else if(item == null && (type == EnumPacketServer.ScriptPlayerGet || type == EnumPacketServer.ScriptPlayerSave || type == EnumPacketServer.ScriptForgeGet || type == EnumPacketServer.ScriptForgeSave)) + else if(item == null && (type == EnumPacketServer.ScriptPlayerGet || type == EnumPacketServer.ScriptPlayerSave || type == EnumPacketServer.ScriptNPCGet || type == EnumPacketServer.ScriptNPCSave || type == EnumPacketServer.ScriptForgeGet || type == EnumPacketServer.ScriptForgeSave)) warn(player, "tried to use custom npcs without a tool in hand, probably a hacker"); else { if (item != null) { @@ -118,6 +119,8 @@ public class PacketHandlerServer{ featherPackets(type, buffer, player); else if (type == EnumPacketServer.ScriptPlayerGet || type == EnumPacketServer.ScriptPlayerSave) playerScriptPackets(type, buffer, player); + else if (type == EnumPacketServer.ScriptNPCGet || type == EnumPacketServer.ScriptNPCSave) + npcScriptPackets(type, buffer, player); else if (type == EnumPacketServer.ScriptForgeGet || type == EnumPacketServer.ScriptForgeSave) forgeScriptPackets(type, buffer, player); else if (item.getItem() == CustomItems.scripter) @@ -172,6 +175,18 @@ public class PacketHandlerServer{ } } + private void npcScriptPackets(EnumPacketServer type, ByteBuf buffer, EntityPlayerMP player) throws Exception { + NBTTagCompound compound; + if(type == EnumPacketServer.ScriptNPCGet) { + NPCDataScript data = ScriptController.Instance.npcScripts; + compound = data.writeToNBT(new NBTTagCompound()); + compound.setTag("Languages", ScriptController.Instance.nbtLanguages()); + Server.sendData(player, EnumPacketClient.GUI_DATA, compound); + } else if(type == EnumPacketServer.ScriptNPCSave) { + ScriptController.Instance.setNPCScripts(Server.readNBT(buffer)); + } + } + private void featherPackets(EnumPacketServer type, ByteBuf buffer, EntityPlayerMP player) throws IOException { if(type == EnumPacketServer.DimensionsGet){ HashMap map = new HashMap(); diff --git a/src/main/java/noppes/npcs/ServerEventsHandler.java b/src/main/java/noppes/npcs/ServerEventsHandler.java index 5d996b6c7..1d964f24c 100644 --- a/src/main/java/noppes/npcs/ServerEventsHandler.java +++ b/src/main/java/noppes/npcs/ServerEventsHandler.java @@ -257,7 +257,7 @@ public class ServerEventsHandler { if(line != null) npc.saySurrounding(line.formatTarget(event.entityLiving)); - npc.script.callScript(EnumScriptType.KILLS, "target", event.entityLiving); + EventHooks.onNPCKilledEntity(npc,event.entityLiving); } EntityPlayer player = null; diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java new file mode 100644 index 000000000..1c4c10c05 --- /dev/null +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptAllNPCs.java @@ -0,0 +1,33 @@ +package noppes.npcs.client.gui.script; + +import net.minecraft.nbt.NBTTagCompound; +import noppes.npcs.client.Client; +import noppes.npcs.client.gui.util.GuiNPCInterface; +import noppes.npcs.constants.EnumPacketServer; +import noppes.npcs.controllers.ScriptController; +import noppes.npcs.controllers.data.ForgeDataScript; +import noppes.npcs.controllers.data.NPCDataScript; + +public class GuiScriptAllNPCs extends GuiScriptInterface { + private NPCDataScript script = new NPCDataScript(null); + + public GuiScriptAllNPCs() { + this.handler = this.script; + Client.sendData(EnumPacketServer.ScriptNPCGet, new Object[0]); + } + + public void setGuiData(NBTTagCompound compound) { + this.script.readFromNBT(compound); + super.setGuiData(compound); + } + + public void save() { + super.save(); + Client.sendData(EnumPacketServer.ScriptNPCSave, new Object[]{this.script.writeToNBT(new NBTTagCompound())}); + } + + public void close() { + super.close(); + ScriptController.Instance.npcScripts.errored.clear(); + } +} diff --git a/src/main/java/noppes/npcs/client/gui/script/GuiScriptGlobal.java b/src/main/java/noppes/npcs/client/gui/script/GuiScriptGlobal.java index 26bfb2834..aecbcda60 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptGlobal.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptGlobal.java @@ -25,6 +25,7 @@ public class GuiScriptGlobal extends GuiNPCInterface { super.initGui(); this.addButton(new GuiNpcButton(0, this.guiLeft + 38, this.guiTop + 20, 100, 20, "Players")); this.addButton(new GuiNpcButton(1, this.guiLeft + 38, this.guiTop + 50, 100, 20, "Forge")); + this.addButton(new GuiNpcButton(2, this.guiLeft + 38, this.guiTop + 80, 100, 20, "NPCs")); } public void drawScreen(int i, int j, float f) { @@ -42,6 +43,9 @@ public class GuiScriptGlobal extends GuiNPCInterface { if (guibutton.id == 1) { this.displayGuiScreen(new GuiScriptForge()); } + if (guibutton.id == 2) { + this.displayGuiScreen(new GuiScriptAllNPCs()); + } } public void keyTyped(char c, int i) { 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 dfe0f38d6..4b0b2928e 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptInterface.java @@ -35,6 +35,7 @@ import noppes.npcs.client.gui.util.*; import noppes.npcs.controllers.IScriptHandler; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.ForgeDataScript; +import noppes.npcs.controllers.data.NPCDataScript; import noppes.npcs.controllers.data.PlayerDataScript; import org.apache.commons.lang3.StringUtils; @@ -147,6 +148,22 @@ public class GuiScriptInterface extends GuiNPCInterface implements GuiYesNoCallb hookList.add("customGuiSlot"); hookList.add("customGuiScroll"); hookList.add("customGuiTextfield"); + + } + else if(handler instanceof NPCDataScript) { + hookList.add("init"); + hookList.add("tick"); + hookList.add("interact"); + hookList.add("dialog"); + hookList.add("damaged"); + hookList.add("killed"); + hookList.add("meleeAttack"); + hookList.add("rangedLaunched"); + hookList.add("target"); + hookList.add("collide"); + hookList.add("kills"); + hookList.add("dialogClose"); + hookList.add("timer"); } else if(handler instanceof ForgeDataScript) { hooks.setSize(238, 198); diff --git a/src/main/java/noppes/npcs/constants/EnumPacketServer.java b/src/main/java/noppes/npcs/constants/EnumPacketServer.java index 4591be8c4..2c5f3f0c3 100644 --- a/src/main/java/noppes/npcs/constants/EnumPacketServer.java +++ b/src/main/java/noppes/npcs/constants/EnumPacketServer.java @@ -40,6 +40,9 @@ public enum EnumPacketServer { ScriptForgeSave(CustomNpcsPermissions.TOOL_SCRIPTER, false), ScriptForgeGet(false), + ScriptNPCSave(CustomNpcsPermissions.TOOL_SCRIPTER, false), + ScriptNPCGet(false), + LinkedGetAll, LinkedRemove(CustomNpcsPermissions.GLOBAL_LINKED), LinkedAdd(CustomNpcsPermissions.GLOBAL_LINKED), ScriptDataSave(CustomNpcsPermissions.TOOL_SCRIPTER, true), ScriptDataGet(true), PlayerDataRemove(CustomNpcsPermissions.GLOBAL_PLAYERDATA), diff --git a/src/main/java/noppes/npcs/controllers/ScriptController.java b/src/main/java/noppes/npcs/controllers/ScriptController.java index e27828a06..7e7e7f36a 100644 --- a/src/main/java/noppes/npcs/controllers/ScriptController.java +++ b/src/main/java/noppes/npcs/controllers/ScriptController.java @@ -29,6 +29,7 @@ import net.minecraftforge.event.world.WorldEvent; import noppes.npcs.CustomNpcs; import noppes.npcs.LogWriter; import noppes.npcs.controllers.data.ForgeDataScript; +import noppes.npcs.controllers.data.NPCDataScript; import noppes.npcs.controllers.data.PlayerDataScript; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.entity.*; @@ -56,6 +57,8 @@ public class ScriptController { public ForgeDataScript forgeScripts = new ForgeDataScript(); + public NPCDataScript npcScripts = new NPCDataScript((EntityNPCInterface) null); + public ScriptController(){ loaded = false; Instance = this; @@ -111,6 +114,10 @@ public class ScriptController { return new File(dir, "player_scripts.json"); } + private File npcScriptsFile() { + return new File(dir, "npc_scripts.json"); + } + public boolean loadPlayerScripts() { this.playerScripts.clear(); File file = this.playerScriptsFile(); @@ -143,6 +150,37 @@ public class ScriptController { } } + public boolean loadNPCScripts() { + this.npcScripts.clear(); + File file = this.npcScriptsFile(); + + try { + if(!file.exists()) { + return false; + } else { + this.npcScripts.readFromNBT(NBTJsonUtil.LoadFile(file)); + shouldSave = false; + return true; + } + } catch (Exception var3) { + LogWriter.error("Error loading: " + file.getAbsolutePath(), var3); + return false; + } + } + + public void setNPCScripts(NBTTagCompound compound) { + this.npcScripts.readFromNBT(compound); + File file = this.npcScriptsFile(); + + try { + NBTJsonUtil.SaveFile(file, compound); + } catch (IOException var4) { + var4.printStackTrace(); + } catch (JsonException var5) { + var5.printStackTrace(); + } + } + private void loadCategories(){ dir = new File(CustomNpcs.getWorldSaveDirectory(), "scripts"); if(!dir.exists()) diff --git a/src/main/java/noppes/npcs/controllers/data/NPCDataScript.java b/src/main/java/noppes/npcs/controllers/data/NPCDataScript.java new file mode 100644 index 000000000..0841ed306 --- /dev/null +++ b/src/main/java/noppes/npcs/controllers/data/NPCDataScript.java @@ -0,0 +1,298 @@ +package noppes.npcs.controllers.data; + +import com.google.common.base.Preconditions; +import cpw.mods.fml.common.eventhandler.Event; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import noppes.npcs.EventHooks; +import noppes.npcs.NBTTags; +import noppes.npcs.constants.EnumScriptType; +import noppes.npcs.controllers.IScriptHandler; +import noppes.npcs.controllers.ScriptContainer; +import noppes.npcs.controllers.ScriptController; +import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.scripted.entity.ScriptNpc; +import noppes.npcs.scripted.interfaces.ICustomNpc; + +import javax.annotation.CheckForNull; +import java.lang.reflect.Array; +import java.util.*; + +public class NPCDataScript implements IScriptHandler { + public List scripts = new ArrayList(); + public String scriptLanguage = "ECMAScript"; + private EntityNPCInterface npc; + private ICustomNpc npcAPI; + public long lastInited = -1L; + public boolean enabled = false; + private Map console = new TreeMap(); + public List errored = new ArrayList(); + + public NPCDataScript(EntityNPCInterface npc) { + if(npc != null) { + this.npc = npc; + } + } + public void clear() { + this.console = new TreeMap(); + this.errored = new ArrayList(); + this.scripts = new ArrayList(); + } + public void readFromNBT(NBTTagCompound compound) { + this.scripts = NBTTags.GetScript(compound.getTagList("Scripts", 10), this); + this.scriptLanguage = compound.getString("ScriptLanguage"); + this.enabled = compound.getBoolean("ScriptEnabled"); + this.console = NBTTags.GetLongStringMap(compound.getTagList("ScriptConsole", 10)); + } + public NBTTagCompound writeToNBT(NBTTagCompound compound) { + compound.setTag("Scripts", NBTTags.NBTScript(this.scripts)); + compound.setString("ScriptLanguage", this.scriptLanguage); + compound.setBoolean("ScriptEnabled", this.enabled); + compound.setTag("ScriptConsole", NBTTags.NBTLongStringMap(this.console)); + return compound; + } + + public void callScript(EnumScriptType type, Event event) { + if (this.isEnabled()) { + ScriptContainer script; + if (ScriptController.Instance.lastLoaded > this.lastInited) { + this.lastInited = ScriptController.Instance.lastLoaded; + errored.clear(); + } + + for(int i = 0; i < ScriptController.Instance.npcScripts.scripts.size(); ++i) { + script = (ScriptContainer)ScriptController.Instance.npcScripts.scripts.get(i); + if (!errored.contains(i)) { + if(script == null || script.errored || !script.hasCode() || ScriptController.Instance.npcScripts.errored.contains(i)) + return; + + script.run(type, event); + + if (script.errored) { + ScriptController.Instance.npcScripts.errored.add(i); + } + + Iterator var8 = script.console.entrySet().iterator(); + + while(var8.hasNext()) { + Map.Entry entry = (Map.Entry)var8.next(); + if (!ScriptController.Instance.npcScripts.console.containsKey(entry.getKey())) { + ScriptController.Instance.npcScripts.console.put(entry.getKey(), " tab " + (i + 1) + ":\n" + (String)entry.getValue()); + } + } + + script.console.clear(); + } + } + + } + } + + public boolean isEnabled() { + return ScriptController.Instance.npcScripts.enabled && ScriptController.HasStart && (this.npc == null || !this.npc.worldObj.isRemote); + } + public boolean isClient() { + return this.npc.isClientWorld(); + } + public boolean getEnabled() { + return ScriptController.Instance.npcScripts.enabled; + } + public void setEnabled(boolean bo) { + ScriptController.Instance.npcScripts.enabled = bo; + this.enabled = bo; + } + public String getLanguage() { + return ScriptController.Instance.npcScripts.scriptLanguage; + } + public void setLanguage(String lang) { + this.scriptLanguage = lang; + } + public List getScripts() { + return this.scripts; + } + public String noticeString() { + if(this.npc == null) { + return "Global script"; + } else { + BlockPos pos = new BlockPos(this.npc); + return NPCDataScript.toStringHelper(this.npc).add("x", pos.getX()).add("y", pos.getY()).add("z", pos.getZ()).toString(); + } + } + public ICustomNpc getNpc() { + if (this.npcAPI == null) { + this.npcAPI = (ICustomNpc) NpcAPI.Instance().getIEntity(this.npc); + } + return this.npcAPI; + } + public Map getConsoleText() { + return this.console; + } + public void clearConsole() { + this.console.clear(); + } + public static final class ToStringHelper { + private final String className; + private final NPCDataScript.ToStringHelper.ValueHolder holderHead; + private NPCDataScript.ToStringHelper.ValueHolder holderTail; + private boolean omitNullValues; + private boolean omitEmptyValues; + private ToStringHelper(String className) { + this.holderHead = new NPCDataScript.ToStringHelper.ValueHolder(); + this.holderTail = this.holderHead; + this.omitNullValues = false; + this.omitEmptyValues = false; + this.className = (String) Preconditions.checkNotNull(className); + } + public NPCDataScript.ToStringHelper omitNullValues() { + this.omitNullValues = true; + return this; + } + public NPCDataScript.ToStringHelper add(String name, @CheckForNull Object value) { + return this.addHolder(name, value); + } + public NPCDataScript.ToStringHelper add(String name, boolean value) { + return this.addUnconditionalHolder(name, String.valueOf(value)); + } + public NPCDataScript.ToStringHelper add(String name, char value) { + return this.addUnconditionalHolder(name, String.valueOf(value)); + } + public NPCDataScript.ToStringHelper add(String name, double value) { + return this.addUnconditionalHolder(name, String.valueOf(value)); + } + public NPCDataScript.ToStringHelper add(String name, float value) { + return this.addUnconditionalHolder(name, String.valueOf(value)); + } + public NPCDataScript.ToStringHelper add(String name, int value) { + return this.addUnconditionalHolder(name, String.valueOf(value)); + } + public NPCDataScript.ToStringHelper add(String name, long value) { + return this.addUnconditionalHolder(name, String.valueOf(value)); + } + public NPCDataScript.ToStringHelper addValue(@CheckForNull Object value) { + return this.addHolder(value); + } + public NPCDataScript.ToStringHelper addValue(boolean value) { + return this.addUnconditionalHolder(String.valueOf(value)); + } + public NPCDataScript.ToStringHelper addValue(char value) { + return this.addUnconditionalHolder(String.valueOf(value)); + } + public NPCDataScript.ToStringHelper addValue(double value) { + return this.addUnconditionalHolder(String.valueOf(value)); + } + public NPCDataScript.ToStringHelper addValue(float value) { + return this.addUnconditionalHolder(String.valueOf(value)); + } + public NPCDataScript.ToStringHelper addValue(int value) { + return this.addUnconditionalHolder(String.valueOf(value)); + } + public NPCDataScript.ToStringHelper addValue(long value) { + return this.addUnconditionalHolder(String.valueOf(value)); + } + private static boolean isEmpty(Object value) { + if (value instanceof CharSequence) { + return ((CharSequence)value).length() == 0; + } else if (value instanceof Collection) { + return ((Collection)value).isEmpty(); + } else if (value instanceof Map) { + return ((Map)value).isEmpty(); + } else if (value instanceof Optional) { + return !((Optional)value).isPresent(); + } else if (value instanceof OptionalInt) { + return !((OptionalInt)value).isPresent(); + } else if (value instanceof OptionalLong) { + return !((OptionalLong)value).isPresent(); + } else if (value instanceof OptionalDouble) { + return !((OptionalDouble)value).isPresent(); + } else if (value instanceof com.google.common.base.Optional) { + return !((com.google.common.base.Optional)value).isPresent(); + } else if (value.getClass().isArray()) { + return Array.getLength(value) == 0; + } else { + return false; + } + } + public String toString() { + boolean omitNullValuesSnapshot = this.omitNullValues; + boolean omitEmptyValuesSnapshot = this.omitEmptyValues; + String nextSeparator = ""; + StringBuilder builder = (new StringBuilder(32)).append(this.className).append('{'); + for(NPCDataScript.ToStringHelper.ValueHolder valueHolder = this.holderHead.next; valueHolder != null; valueHolder = valueHolder.next) { + Object value = valueHolder.value; + if (!(valueHolder instanceof NPCDataScript.ToStringHelper.UnconditionalValueHolder)) { + if (value == null) { + if (omitNullValuesSnapshot) { + continue; + } + } else if (omitEmptyValuesSnapshot && isEmpty(value)) { + continue; + } + } + builder.append(nextSeparator); + nextSeparator = ", "; + if (valueHolder.name != null) { + builder.append(valueHolder.name).append('='); + } + if (value != null && value.getClass().isArray()) { + Object[] objectArray = new Object[]{value}; + String arrayString = Arrays.deepToString(objectArray); + builder.append(arrayString, 1, arrayString.length() - 1); + } else { + builder.append(value); + } + } + return builder.append('}').toString(); + } + private NPCDataScript.ToStringHelper.ValueHolder addHolder() { + NPCDataScript.ToStringHelper.ValueHolder valueHolder = new NPCDataScript.ToStringHelper.ValueHolder(); + this.holderTail = this.holderTail.next = valueHolder; + return valueHolder; + } + private NPCDataScript.ToStringHelper addHolder(@CheckForNull Object value) { + NPCDataScript.ToStringHelper.ValueHolder valueHolder = this.addHolder(); + valueHolder.value = value; + return this; + } + private NPCDataScript.ToStringHelper addHolder(String name, @CheckForNull Object value) { + NPCDataScript.ToStringHelper.ValueHolder valueHolder = this.addHolder(); + valueHolder.value = value; + valueHolder.name = (String)Preconditions.checkNotNull(name); + return this; + } + private NPCDataScript.ToStringHelper.UnconditionalValueHolder addUnconditionalHolder() { + NPCDataScript.ToStringHelper.UnconditionalValueHolder valueHolder = new NPCDataScript.ToStringHelper.UnconditionalValueHolder(); + this.holderTail = this.holderTail.next = valueHolder; + return valueHolder; + } + private NPCDataScript.ToStringHelper addUnconditionalHolder(Object value) { + NPCDataScript.ToStringHelper.UnconditionalValueHolder valueHolder = this.addUnconditionalHolder(); + valueHolder.value = value; + return this; + } + private NPCDataScript.ToStringHelper addUnconditionalHolder(String name, Object value) { + NPCDataScript.ToStringHelper.UnconditionalValueHolder valueHolder = this.addUnconditionalHolder(); + valueHolder.value = value; + valueHolder.name = (String)Preconditions.checkNotNull(name); + return this; + } + private static final class UnconditionalValueHolder extends NPCDataScript.ToStringHelper.ValueHolder { + private UnconditionalValueHolder() { + super(); + } + } + private static class ValueHolder { + @CheckForNull + String name; + @CheckForNull + Object value; + @CheckForNull + NPCDataScript.ToStringHelper.ValueHolder next; + private ValueHolder() { + } + } + } + public static NPCDataScript.ToStringHelper toStringHelper(Object self) { + return new NPCDataScript.ToStringHelper(self.getClass().getSimpleName()); + } +} diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index 54ec303ae..ab09fdecc 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -40,20 +40,7 @@ import net.minecraft.world.WorldServer; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.ServerChatEvent; -import noppes.npcs.CustomItems; -import noppes.npcs.CustomNpcs; -import noppes.npcs.DataAI; -import noppes.npcs.DataAdvanced; -import noppes.npcs.DataDisplay; -import noppes.npcs.DataInventory; -import noppes.npcs.DataScript; -import noppes.npcs.DataStats; -import noppes.npcs.IChatMessages; -import noppes.npcs.NBTTags; -import noppes.npcs.NoppesUtilServer; -import noppes.npcs.NpcDamageSource; -import noppes.npcs.Server; -import noppes.npcs.VersionCompatibility; +import noppes.npcs.*; import noppes.npcs.ai.*; import noppes.npcs.ai.EntityAIMoveIndoors; import noppes.npcs.ai.EntityAIPanic; @@ -233,8 +220,9 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti @Override public void onUpdate(){ super.onUpdate(); - if(this.ticksExisted % 10 == 0) - script.callScript(EnumScriptType.TICK); + if(this.ticksExisted % 10 == 0) { + EventHooks.onNPCUpdate(this); + } this.timers.update(); } @@ -257,7 +245,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } if(par1Entity instanceof EntityLivingBase){ ScriptEventAttack event = new ScriptEventAttack(f, (EntityLivingBase)par1Entity, false); - if(script.callScript(EnumScriptType.ATTACK, "event", event, "target", par1Entity)) + if(EventHooks.onNPCMeleeAttack(this, f, (EntityLivingBase)par1Entity)) return false; f = event.getDamage(); } @@ -398,8 +386,8 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti return true; } } - - if(script.callScript(EnumScriptType.INTERACT, "player", player) || isAttacking() || isKilled() || faction.isAggressiveToPlayer(player)) + + if(EventHooks.onNPCInteract(this, player) || isAttacking() || isKilled() || faction.isAggressiveToPlayer(player)) return false; addInteract(player); @@ -515,7 +503,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti else if (attackingEntity instanceof EntityPlayer && faction.isFriendlyToPlayer((EntityPlayer) attackingEntity)) return false; ScriptEventDamaged result = new ScriptEventDamaged(i, attackingEntity, damagesource); - if(script.callScript(EnumScriptType.DAMAGED, "event", result) || isKilled()) + if(EventHooks.onNPCDamaged(this, attackingEntity, i, damagesource, result) || isKilled()) return false; i = result.getDamage(); @@ -565,7 +553,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti return; if(getAttackTarget() != entity && entity != null){ ScriptEventTarget event = new ScriptEventTarget(entity); - if(script.callScript(EnumScriptType.TARGET, "event", event)) + if(EventHooks.onNPCTarget(this,entity)) return; if(event.getTarget() == null) @@ -590,7 +578,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti return; } ScriptEventAttack event = new ScriptEventAttack(stats.pDamage, entity, true); - if(script.callScript(EnumScriptType.ATTACK, "event", event, "target", entity)) + if(EventHooks.onNPCRangedAttack(this, f, (EntityLivingBase)entity)) return; for(int i = 0; i < this.stats.shotCount; i++) { @@ -919,7 +907,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti } public void saySurrounding(Line line) { - if (line == null || line.text == null) + if (line == null || line.text == null || getFakePlayer() == null) return; ServerChatEvent event = new ServerChatEvent(getFakePlayer(), line.text, new ChatComponentTranslation(line.text.replace("%", "%%"))); if (MinecraftForge.EVENT_BUS.post(event) || event.component == null){ @@ -1072,7 +1060,8 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti if(jobInterface != null) jobInterface.reset(); - + + EventHooks.onNPCInit(this); script.callScript(EnumScriptType.INIT); } @@ -1095,8 +1084,9 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti for (int i = 0; i < list.size(); ++i){ Entity entity = (Entity)list.get(i); - if (entity.isEntityAlive()) - script.callScript(EnumScriptType.COLLIDE, "entity", entity); + if (entity.isEntityAlive()) { + EventHooks.onNPCCollide(this,entity); + } } } @@ -1223,7 +1213,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti attackingEntity = ((EntityThrowable) entity).getThrower(); ScriptEventKilled result = new ScriptEventKilled(attackingEntity, damagesource); - if(script.callScript(EnumScriptType.KILLED, "event", result)) + if(EventHooks.onNPCKilled(this,damagesource,attackingEntity,result)) return; if(!isRemote()){ if(this.recentlyHit > 0) diff --git a/src/main/java/noppes/npcs/scripted/event/NpcEvent.java b/src/main/java/noppes/npcs/scripted/event/NpcEvent.java index 58994c14d..51d40f67a 100644 --- a/src/main/java/noppes/npcs/scripted/event/NpcEvent.java +++ b/src/main/java/noppes/npcs/scripted/event/NpcEvent.java @@ -10,6 +10,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.DamageSource; +import noppes.npcs.controllers.Dialog; import noppes.npcs.scripted.NpcAPI; import noppes.npcs.scripted.interfaces.*; @@ -51,6 +52,10 @@ public class NpcEvent extends CustomNPCsEvent { this.damage = damage; this.damageSource = NpcAPI.Instance().getIDamageSource(damagesource); } + + public String getType(){ + return damageSource.getMCDamageSource().damageType; + } } public static class RangedLaunchedEvent extends NpcEvent { @@ -58,7 +63,7 @@ public class NpcEvent extends CustomNPCsEvent { public float damage; //public List projectiles = new ArrayList(); - public RangedLaunchedEvent(ICustomNpc npc, EntityLivingBase target, float damage) { + public RangedLaunchedEvent(ICustomNpc npc, float damage, EntityLivingBase target) { super(npc); this.target = (IEntityLivingBase)NpcAPI.Instance().getIEntity(target); this.damage = damage; @@ -70,7 +75,7 @@ public class NpcEvent extends CustomNPCsEvent { public final IEntityLivingBase target; public float damage; - public MeleeAttackEvent(ICustomNpc npc, EntityLivingBase target, float damage) { + public MeleeAttackEvent(ICustomNpc npc, float damage, EntityLivingBase target) { super(npc); this.target = (IEntityLivingBase)NpcAPI.Instance().getIEntity(target); this.damage = damage; @@ -99,6 +104,10 @@ public class NpcEvent extends CustomNPCsEvent { this.type = damagesource.damageType; this.source = NpcAPI.Instance().getIEntity(entity); } + + public String getType(){ + return damageSource.getMCDamageSource().damageType; + } } @Cancelable @@ -111,6 +120,34 @@ public class NpcEvent extends CustomNPCsEvent { } } + public static class DialogEvent extends NpcEvent { + public final IPlayer player; + public final int id; + public final Dialog dialog; + + public DialogEvent(ICustomNpc npc, EntityPlayer player, int id, Dialog dialog) { + super(npc); + this.player = (IPlayer)NpcAPI.Instance().getIEntity(player); + this.id = id; + this.dialog = dialog; + } + } + + public static class DialogClosedEvent extends NpcEvent { + public final IPlayer player; + public final int id; + public final int optionId; + public final Dialog dialog; + + public DialogClosedEvent(ICustomNpc npc, EntityPlayer player, int id, int optionId, Dialog dialog) { + super(npc); + this.player = (IPlayer)NpcAPI.Instance().getIEntity(player); + this.id = id; + this.optionId = optionId; + this.dialog = dialog; + } + } + @Cancelable public static class TargetLostEvent extends NpcEvent { public final IEntityLivingBase entity;