diff --git a/src/main/java/noppes/npcs/CustomNpcs.java b/src/main/java/noppes/npcs/CustomNpcs.java index 5d27c249a..c4ceaa46d 100644 --- a/src/main/java/noppes/npcs/CustomNpcs.java +++ b/src/main/java/noppes/npcs/CustomNpcs.java @@ -315,6 +315,32 @@ public class CustomNpcs { return null; } + public static File getWorldSaveDirectory(String s) { + try { + File dir = new File("."); + if (getServer() != null) { + if (!getServer().isDedicatedServer()) { + dir = new File(Minecraft.getMinecraft().mcDataDir, "saves"); + } + + dir = new File(new File(dir, getServer().getFolderName()), "customnpcs"); + } + + if (s != null) { + dir = new File(dir, s); + } + + if (!dir.exists()) { + dir.mkdirs(); + } + + return dir; + } catch (Exception var2) { + LogWriter.error("Error getting worldsave", var2); + return null; + } + } + public static MinecraftServer getServer(){ return MinecraftServer.getServer(); } diff --git a/src/main/java/noppes/npcs/EventHooks.java b/src/main/java/noppes/npcs/EventHooks.java index d3a5368a8..ea2b619bc 100644 --- a/src/main/java/noppes/npcs/EventHooks.java +++ b/src/main/java/noppes/npcs/EventHooks.java @@ -21,9 +21,9 @@ import net.minecraftforge.event.world.WorldEvent; import noppes.npcs.controllers.ScriptController; import noppes.npcs.controllers.data.ForgeDataScript; import noppes.npcs.controllers.data.PlayerDataScript; +import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.*; -import noppes.npcs.scripted.event.ForgeEvent; -import noppes.npcs.scripted.event.PlayerEvent; +import noppes.npcs.scripted.event.*; import noppes.npcs.scripted.event.PlayerEvent.ChatEvent; import noppes.npcs.scripted.event.PlayerEvent.ContainerOpen; import noppes.npcs.scripted.event.PlayerEvent.DamagedEntityEvent; @@ -46,6 +46,13 @@ public class EventHooks { public EventHooks() { } + 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); + WrapperNpcAPI.EVENT_BUS.post(event); + } + public static void onPlayerInit(PlayerDataScript handler) { noppes.npcs.scripted.event.PlayerEvent.InitEvent event = new noppes.npcs.scripted.event.PlayerEvent.InitEvent(handler.getPlayer()); handler.callScript(EnumScriptType.INIT, event, "event", event); diff --git a/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java b/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java index 2841cf20a..50789cf1c 100644 --- a/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java +++ b/src/main/java/noppes/npcs/ScriptPlayerEventHandler.java @@ -46,6 +46,7 @@ import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.event.world.WorldEvent.PotentialSpawns; import noppes.npcs.controllers.PlayerData; +import noppes.npcs.controllers.PlayerDataController; import noppes.npcs.controllers.data.PlayerDataScript; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.NpcAPI; diff --git a/src/main/java/noppes/npcs/client/gui/GuiScript.java b/src/main/java/noppes/npcs/client/gui/GuiScript.java index 4d84a3fc6..bbdec81d3 100644 --- a/src/main/java/noppes/npcs/client/gui/GuiScript.java +++ b/src/main/java/noppes/npcs/client/gui/GuiScript.java @@ -71,6 +71,7 @@ public class GuiScript extends GuiNPCInterface implements IGuiData, GuiYesNoCall list.add("script.collide"); list.add("script.kills"); list.add("script.dialog_closed"); + list.add("script.timer"); if(showScript){ addLabel(new GuiNpcLabel(0, "script.hooks", guiLeft + 4, guiTop + 5)); diff --git a/src/main/java/noppes/npcs/constants/EnumScriptType.java b/src/main/java/noppes/npcs/constants/EnumScriptType.java index dc545d999..a3980a94a 100644 --- a/src/main/java/noppes/npcs/constants/EnumScriptType.java +++ b/src/main/java/noppes/npcs/constants/EnumScriptType.java @@ -7,11 +7,14 @@ public enum EnumScriptType { DIALOG("dialog"), DAMAGED("damaged"), KILLED("killed"), - ATTACK_MELEE("meleeAttack"), + ATTACK("attack"), TARGET("target"), COLLIDE("collide"), KILLS("kills"), DIALOG_OPTION("dialogOption"), + TIMER("timer"), + + ATTACK_MELEE("meleeAttack"), TARGET_LOST("targetLost"), ROLE("role"), RANGED_CHARGE("rangedCharge"), @@ -25,7 +28,6 @@ public enum EnumScriptType { NEIGHBOR_CHANGED("neighborChanged"), REDSTONE("redstone"), DOOR_TOGGLE("doorToggle"), - TIMER("timer"), TOSS("toss"), DROP("drop"), CONTAINER_OPEN("containerOpen"), @@ -39,7 +41,6 @@ public enum EnumScriptType { TOSSED("tossed"), PICKEDUP("pickedUp"), PICKUP("pickUp"), - ATTACK("attack"), PROJECTILE_TICK("projectileTick"), PROJECTILE_IMPACT("projectileImpact"), LEVEL_UP("levelUp"), diff --git a/src/main/java/noppes/npcs/controllers/PlayerData.java b/src/main/java/noppes/npcs/controllers/PlayerData.java index 69634c971..3139a28c6 100644 --- a/src/main/java/noppes/npcs/controllers/PlayerData.java +++ b/src/main/java/noppes/npcs/controllers/PlayerData.java @@ -2,16 +2,23 @@ package noppes.npcs.controllers; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; import net.minecraft.world.World; import net.minecraftforge.common.IExtendedEntityProperties; import noppes.npcs.CustomNpcs; +import noppes.npcs.LogWriter; import noppes.npcs.constants.EnumRoleType; import noppes.npcs.controllers.data.PlayerDataScript; import noppes.npcs.entity.EntityCustomNpc; import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.entity.data.DataTimers; import noppes.npcs.roles.RoleCompanion; +import noppes.npcs.util.NBTJsonUtil; + +import java.io.File; +import java.io.FileInputStream; public class PlayerData implements IExtendedEntityProperties{ public PlayerDialogData dialogData = new PlayerDialogData(); @@ -145,16 +152,79 @@ public class PlayerData implements IExtendedEntityProperties{ world.spawnEntityInWorld(npc); } + public static NBTTagCompound loadPlayerDataOld(String player) { + File saveDir = CustomNpcs.getWorldSaveDirectory("playerdata"); + String filename = player; + if (player.isEmpty()) { + filename = "noplayername"; + } + + filename = filename + ".dat"; + + File file; + try { + file = new File(saveDir, filename); + if (file.exists()) { + NBTTagCompound comp = CompressedStreamTools.readCompressed(new FileInputStream(file)); + file.delete(); + file = new File(saveDir, filename + "_old"); + if (file.exists()) { + file.delete(); + } + + return comp; + } + } catch (Exception var6) { + LogWriter.except(var6); + } + + try { + file = new File(saveDir, filename + "_old"); + if (file.exists()) { + return CompressedStreamTools.readCompressed(new FileInputStream(file)); + } + } catch (Exception var5) { + LogWriter.except(var5); + } + + return new NBTTagCompound(); + } + + public static NBTTagCompound loadPlayerData(String player) { + File saveDir = CustomNpcs.getWorldSaveDirectory("playerdata"); + String filename = player; + if (player.isEmpty()) { + filename = "noplayername"; + } + + filename = filename + ".json"; + File file = null; + + try { + file = new File(saveDir, filename); + if (file.exists()) { + return NBTJsonUtil.LoadFile(file); + } + } catch (Exception var5) { + LogWriter.error("Error loading: " + file.getAbsolutePath(), var5); + } + + return new NBTTagCompound(); + } + public static PlayerData get(EntityPlayer player) { if(player.worldObj.isRemote) { return CustomNpcs.proxy.getPlayerData(player); } else { PlayerData data = new PlayerData(); - if(data.player == null) { + if (data.player == null) { data.player = player; data.playerLevel = player.experienceLevel; data.scriptData = new PlayerDataScript(player); - NBTTagCompound compound = PlayerDataController.instance.loadPlayerDataOld(player.getCommandSenderName()); + NBTTagCompound compound = loadPlayerData(player.getPersistentID().toString()); + if (compound.hasNoTags()) { + compound = loadPlayerDataOld(player.getCommandSenderName()); + } data.setNBT(compound); } diff --git a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java index ea030ce2c..790c8204b 100644 --- a/src/main/java/noppes/npcs/entity/EntityNPCInterface.java +++ b/src/main/java/noppes/npcs/entity/EntityNPCInterface.java @@ -87,6 +87,7 @@ import noppes.npcs.controllers.PlayerDataController; import noppes.npcs.controllers.PlayerQuestData; import noppes.npcs.controllers.QuestData; import noppes.npcs.controllers.TransformData; +import noppes.npcs.entity.data.DataTimers; import noppes.npcs.roles.JobBard; import noppes.npcs.roles.JobFollower; import noppes.npcs.roles.JobInterface; @@ -115,6 +116,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti public DataInventory inventory; public DataScript script; public TransformData transform; + public DataTimers timers; public String linkedName = ""; public long linkedLast = 0; @@ -190,7 +192,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti inventory = new DataInventory(this); transform = new TransformData(this); script = new DataScript(this); - + timers = new DataTimers(this); this.getAttributeMap().registerAttribute(SharedMonsterAttributes.attackDamage); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(stats.maxHealth); @@ -226,6 +228,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti super.onUpdate(); if(this.ticksExisted % 10 == 0) script.callScript(EnumScriptType.TICK); + this.timers.update(); } public void setWorld(World world){ @@ -920,7 +923,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti stats.readToNBT(compound); ai.readToNBT(compound); script.readFromNBT(compound); - + timers.readFromNBT(compound); advanced.readToNBT(compound); if (advanced.role != EnumRoleType.None && roleInterface != null) roleInterface.readFromNBT(compound); @@ -951,7 +954,7 @@ public abstract class EntityNPCInterface extends EntityCreature implements IEnti stats.writeToNBT(compound); ai.writeToNBT(compound); script.writeToNBT(compound); - + timers.writeToNBT(compound); advanced.writeToNBT(compound); if (advanced.role != EnumRoleType.None && roleInterface != null) roleInterface.writeToNBT(compound); diff --git a/src/main/java/noppes/npcs/entity/data/DataTimers.java b/src/main/java/noppes/npcs/entity/data/DataTimers.java index 843d38849..d51012961 100644 --- a/src/main/java/noppes/npcs/entity/data/DataTimers.java +++ b/src/main/java/noppes/npcs/entity/data/DataTimers.java @@ -12,6 +12,7 @@ import java.util.Map; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import noppes.npcs.EventHooks; +import noppes.npcs.entity.EntityNPCInterface; import noppes.npcs.scripted.interfaces.ITimers; import noppes.npcs.controllers.PlayerData; import noppes.npcs.scripted.CustomNPCsException; @@ -24,16 +25,29 @@ public class DataTimers implements ITimers { this.parent = parent; } + private void saveNbt() { + if(parent instanceof PlayerData) { + PlayerData playerData = (PlayerData) parent; + playerData.saveNBTData(null); + } + else if(parent instanceof PlayerData) { + PlayerData playerData = (PlayerData) parent; + playerData.saveNBTData(null); + } + } + public void start(int id, int ticks, boolean repeat) { if(this.timers.containsKey(Integer.valueOf(id))) { throw new CustomNPCsException("There is already a timer with id: " + id, new Object[0]); } else { this.timers.put(Integer.valueOf(id), new DataTimers.Timer(id, ticks, repeat)); + saveNbt(); } } public void forceStart(int id, int ticks, boolean repeat) { this.timers.put(Integer.valueOf(id), new DataTimers.Timer(id, ticks, repeat)); + saveNbt(); } public boolean has(int id) { @@ -41,7 +55,9 @@ public class DataTimers implements ITimers { } public boolean stop(int id) { - return this.timers.remove(Integer.valueOf(id)) != null; + boolean remove = this.timers.remove(Integer.valueOf(id)) != null; + saveNbt(); + return remove; } public void reset(int id) { @@ -50,6 +66,7 @@ public class DataTimers implements ITimers { throw new CustomNPCsException("There is no timer with id: " + id, new Object[0]); } else { timer.ticks = 0; + saveNbt(); } } @@ -71,14 +88,14 @@ public class DataTimers implements ITimers { } public void readFromNBT(NBTTagCompound compound) { - HashMap timers = new HashMap(); + Map timers = new HashMap(); NBTTagList list = compound.getTagList("NpcsTimers", 10); for(int i = 0; i < list.tagCount(); ++i) { NBTTagCompound c = list.getCompoundTagAt(i); DataTimers.Timer t = new DataTimers.Timer(c.getInteger("ID"), c.getInteger("TimerTicks"), c.getBoolean("Repeat")); t.ticks = c.getInteger("Ticks"); - timers.put(Integer.valueOf(t.id), t); + timers.put(t.id, t); } this.timers = timers; @@ -91,11 +108,12 @@ public class DataTimers implements ITimers { DataTimers.Timer timer = (DataTimers.Timer)var1.next(); timer.update(); } - + saveNbt(); } public void clear() { this.timers = new HashMap(); + saveNbt(); } class Timer { @@ -120,7 +138,10 @@ public class DataTimers implements ITimers { } Object ob = DataTimers.this.parent; - if(ob instanceof PlayerData) { + if (ob instanceof EntityNPCInterface) { + EventHooks.onNPCTimer((EntityNPCInterface)ob, this.id); + } + else if(ob instanceof PlayerData) { EventHooks.onPlayerTimer((PlayerData)ob, this.id); } } diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java b/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java index 2b1b9473c..65a136a2b 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptNpc.java @@ -13,6 +13,7 @@ import noppes.npcs.scripted.ScriptItemStack; import noppes.npcs.scripted.constants.AnimationType; import noppes.npcs.scripted.constants.EntityType; import noppes.npcs.scripted.interfaces.ICustomNpc; +import noppes.npcs.scripted.interfaces.ITimers; import noppes.npcs.scripted.roles.ScriptJobBard; import noppes.npcs.scripted.roles.ScriptJobConversation; import noppes.npcs.scripted.roles.ScriptJobFollower; @@ -678,4 +679,8 @@ public class ScriptNpc extends ScriptLiving imp public long getAge(){ return npc.totalTicksAlive; } + + public ITimers getTimers() { + return ((EntityNPCInterface)this.npc).timers; + } } diff --git a/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java b/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java index 0d967cfee..08934d55d 100644 --- a/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java +++ b/src/main/java/noppes/npcs/scripted/entity/ScriptPlayer.java @@ -1,5 +1,6 @@ package noppes.npcs.scripted.entity; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -26,10 +27,12 @@ import noppes.npcs.scripted.ScriptItemStack; import noppes.npcs.scripted.ScriptPixelmonPlayerData; import noppes.npcs.scripted.constants.EntityType; import noppes.npcs.scripted.interfaces.IPlayer; +import noppes.npcs.scripted.interfaces.ITimers; import noppes.npcs.util.ValueUtil; public class ScriptPlayer extends ScriptLivingBase implements IPlayer { public T player; + private PlayerData data; public ScriptPlayer(T player){ super(player); this.player = player; @@ -350,4 +353,16 @@ public class ScriptPlayer extends ScriptLivingBase return null; return new ScriptPixelmonPlayerData(player); } + + private PlayerData getData() { + if (this.data == null) { + this.data = PlayerData.get(player); + } + + return this.data; + } + + public ITimers getTimers() { + return this.getData().timers; + } } diff --git a/src/main/java/noppes/npcs/scripted/event/NpcEvent.java b/src/main/java/noppes/npcs/scripted/event/NpcEvent.java new file mode 100644 index 000000000..58994c14d --- /dev/null +++ b/src/main/java/noppes/npcs/scripted/event/NpcEvent.java @@ -0,0 +1,145 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package noppes.npcs.scripted.event; + +import cpw.mods.fml.common.eventhandler.Cancelable; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.DamageSource; +import noppes.npcs.scripted.NpcAPI; +import noppes.npcs.scripted.interfaces.*; + +public class NpcEvent extends CustomNPCsEvent { + public final ICustomNpc npc; + + public NpcEvent(ICustomNpc npc) { + this.npc = npc; + } + + public static class TimerEvent extends NpcEvent { + public final int id; + + public TimerEvent(ICustomNpc npc, int id) { + super(npc); + this.id = id; + } + } + + public static class CollideEvent extends NpcEvent { + public final IEntity entity; + + public CollideEvent(ICustomNpc npc, Entity entity) { + super(npc); + this.entity = NpcAPI.Instance().getIEntity(entity); + } + } + + @Cancelable + public static class DamagedEvent extends NpcEvent { + public final IDamageSource damageSource; + public final IEntity source; + public float damage; + public boolean clearTarget = false; + + public DamagedEvent(ICustomNpc npc, Entity source, float damage, DamageSource damagesource) { + super(npc); + this.source = NpcAPI.Instance().getIEntity(source); + this.damage = damage; + this.damageSource = NpcAPI.Instance().getIDamageSource(damagesource); + } + } + + public static class RangedLaunchedEvent extends NpcEvent { + public final IEntityLivingBase target; + public float damage; + //public List projectiles = new ArrayList(); + + public RangedLaunchedEvent(ICustomNpc npc, EntityLivingBase target, float damage) { + super(npc); + this.target = (IEntityLivingBase)NpcAPI.Instance().getIEntity(target); + this.damage = damage; + } + } + + @Cancelable + public static class MeleeAttackEvent extends NpcEvent { + public final IEntityLivingBase target; + public float damage; + + public MeleeAttackEvent(ICustomNpc npc, EntityLivingBase target, float damage) { + super(npc); + this.target = (IEntityLivingBase)NpcAPI.Instance().getIEntity(target); + this.damage = damage; + } + } + + public static class KilledEntityEvent extends NpcEvent { + public final IEntityLivingBase entity; + + public KilledEntityEvent(ICustomNpc npc, EntityLivingBase entity) { + super(npc); + this.entity = (IEntityLivingBase)NpcAPI.Instance().getIEntity(entity); + } + } + + public static class DiedEvent extends NpcEvent { + public final IDamageSource damageSource; + public final String type; + public final IEntity source; + public IItemStack[] droppedItems; + public int expDropped; + + public DiedEvent(ICustomNpc npc, DamageSource damagesource, Entity entity) { + super(npc); + this.damageSource = NpcAPI.Instance().getIDamageSource(damagesource); + this.type = damagesource.damageType; + this.source = NpcAPI.Instance().getIEntity(entity); + } + } + + @Cancelable + public static class InteractEvent extends NpcEvent { + public final IPlayer player; + + public InteractEvent(ICustomNpc npc, EntityPlayer player) { + super(npc); + this.player = (IPlayer)NpcAPI.Instance().getIEntity(player); + } + } + + @Cancelable + public static class TargetLostEvent extends NpcEvent { + public final IEntityLivingBase entity; + + public TargetLostEvent(ICustomNpc npc, EntityLivingBase entity) { + super(npc); + this.entity = (IEntityLivingBase)NpcAPI.Instance().getIEntity(entity); + } + } + + @Cancelable + public static class TargetEvent extends NpcEvent { + public IEntityLivingBase entity; + + public TargetEvent(ICustomNpc npc, EntityLivingBase entity) { + super(npc); + this.entity = (IEntityLivingBase) NpcAPI.Instance().getIEntity(entity); + } + } + + public static class UpdateEvent extends NpcEvent { + public UpdateEvent(ICustomNpc npc) { + super(npc); + } + } + + public static class InitEvent extends NpcEvent { + public InitEvent(ICustomNpc npc) { + super(npc); + } + } +} diff --git a/src/main/java/noppes/npcs/scripted/event/ScriptEventTarget.java b/src/main/java/noppes/npcs/scripted/event/ScriptEventTarget.java index c5aef813c..1bb9832c2 100644 --- a/src/main/java/noppes/npcs/scripted/event/ScriptEventTarget.java +++ b/src/main/java/noppes/npcs/scripted/event/ScriptEventTarget.java @@ -4,7 +4,7 @@ import net.minecraft.entity.EntityLivingBase; import noppes.npcs.controllers.ScriptController; import noppes.npcs.scripted.entity.ScriptLivingBase; -public class ScriptEventTarget extends ScriptEvent{ +public class ScriptEventTarget extends ScriptEvent { private ScriptLivingBase target; diff --git a/src/main/java/noppes/npcs/scripted/event/ScriptEventTimer.java b/src/main/java/noppes/npcs/scripted/event/ScriptEventTimer.java new file mode 100644 index 000000000..0fdc3584b --- /dev/null +++ b/src/main/java/noppes/npcs/scripted/event/ScriptEventTimer.java @@ -0,0 +1,13 @@ +package noppes.npcs.scripted.event; + +public class ScriptEventTimer extends ScriptEvent { + private int id; + + public ScriptEventTimer(int id){ + this.id = id; + } + + public int getId(){ + return id; + } +} diff --git a/src/main/java/noppes/npcs/scripted/interfaces/IPlayer.java b/src/main/java/noppes/npcs/scripted/interfaces/IPlayer.java index 495ecbb1a..a4254fcb9 100644 --- a/src/main/java/noppes/npcs/scripted/interfaces/IPlayer.java +++ b/src/main/java/noppes/npcs/scripted/interfaces/IPlayer.java @@ -166,4 +166,6 @@ public interface IPlayer extends IEntityLivingBase * @since 1.7.10d */ public ScriptPixelmonPlayerData getPixelmonData(); + + public ITimers getTimers(); } diff --git a/src/main/resources/assets/customnpcs/lang/en_US.lang b/src/main/resources/assets/customnpcs/lang/en_US.lang index ba4b81182..7a022e197 100644 --- a/src/main/resources/assets/customnpcs/lang/en_US.lang +++ b/src/main/resources/assets/customnpcs/lang/en_US.lang @@ -459,6 +459,7 @@ script.damaged=Damaged script.killed=Killed script.attack=Attack script.target=Target +script.timer=Timer script.availableScripts=Available Scripts script.loadedScripts=Loaded Scripts script.collide=Collide