diff --git a/src/main/java/noppes/npcs/CommonProxy.java b/src/main/java/noppes/npcs/CommonProxy.java index 067e2f1b3..4bf6458d7 100644 --- a/src/main/java/noppes/npcs/CommonProxy.java +++ b/src/main/java/noppes/npcs/CommonProxy.java @@ -1,7 +1,11 @@ package noppes.npcs; import cpw.mods.fml.common.network.IGuiHandler; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBiped; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; @@ -14,19 +18,111 @@ import noppes.npcs.api.IWorld; import noppes.npcs.blocks.tiles.TileNpcContainer; import noppes.npcs.constants.EnumGuiType; import noppes.npcs.containers.*; +import noppes.npcs.controllers.data.AnimationData; +import noppes.npcs.controllers.data.Frame; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.util.MillisTimer; + +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.HashSet; public class CommonProxy implements IGuiHandler { + public final static HashSet clientPlayingAnimations = new HashSet<>(); + public final static HashSet serverPlayingAnimations = new HashSet<>(); + protected MillisTimer animationTimer = new MillisTimer(1000); + protected static long totalServerTicks; + protected static long totalClientTicks; public boolean newVersionAvailable = false; public int revision = 1; public void load() { + this.createAnimationThread(); + CustomNpcs.Channel.register(new PacketHandlerServer()); CustomNpcs.ChannelPlayer.register(new PacketHandlerPlayer()); } + protected void createAnimationThread() { + Thread thread = (new Thread("Animation Thread") { public void run() { + while (true) { + try { + if (!CustomNpcs.proxy.hasClient() || !Minecraft.getMinecraft().isGamePaused()) { + animationTimer.updateTimer(); + } + + for (int i = 0; i < animationTimer.elapsedTicks; ++i) { + updateData(totalClientTicks, clientPlayingAnimations); + totalClientTicks++; + + updateData(totalServerTicks, serverPlayingAnimations); + totalServerTicks++; + } + + totalClientTicks %= Long.MAX_VALUE; + totalServerTicks %= Long.MAX_VALUE; + + synchronized (clientPlayingAnimations) { + clientPlayingAnimations.removeIf(CommonProxy.this::removeAnimation); + } + synchronized (serverPlayingAnimations) { + serverPlayingAnimations.removeIf(CommonProxy.this::removeAnimation); + } + } catch (Exception e) { + if (!(e instanceof ConcurrentModificationException)) { + e.printStackTrace(); + } + } + } + }}); + thread.setDaemon(true); + thread.start(); + } + + private void updateData(long ticks, Collection animationData) { + for (AnimationData data : animationData) { + Frame frame = data.animation != null && data.animation.currentFrame() != null + ? (Frame) data.animation.currentFrame() : null; + if (frame != null) { + int tickDuration = frame.tickDuration(); + if (ticks % tickDuration == 0) { + data.increaseTime(); + } + } + } + } + + private boolean removeAnimation(AnimationData data) { + Entity entity = null; + if (data.parent instanceof DataDisplay) { + entity = ((DataDisplay)data.parent).npc; + } else { + if (data.parent instanceof PlayerData) { + entity = ((PlayerData) data.parent).player; + } else if (data.parent instanceof EntityPlayer) { + entity = (EntityPlayer) data.parent; + } + } + + if (entity == null) return true; + + if (entity.worldObj != null && entity.worldObj.isRemote) { + return clientRemoveAnimation(entity); + } else { + return entity.worldObj == null || !entity.worldObj.loadedEntityList.contains(entity) + || CustomNpcs.getServer().isServerStopped(); + } + } + + @SideOnly(Side.CLIENT) + private boolean clientRemoveAnimation(Entity entity) { + Minecraft mc = Minecraft.getMinecraft(); + return mc.theWorld == null + || mc.currentScreen == null && entity != mc.thePlayer && !mc.theWorld.loadedEntityList.contains(entity); + } + public PlayerData getPlayerData(EntityPlayer player) { return null; } @@ -166,4 +262,4 @@ public class CommonProxy implements IGuiHandler { public boolean isGUIOpen(){ return false; } -} \ No newline at end of file +} diff --git a/src/main/java/noppes/npcs/client/ClientEventHandler.java b/src/main/java/noppes/npcs/client/ClientEventHandler.java index dfd5336f2..d8b576aa1 100644 --- a/src/main/java/noppes/npcs/client/ClientEventHandler.java +++ b/src/main/java/noppes/npcs/client/ClientEventHandler.java @@ -32,8 +32,6 @@ import java.lang.reflect.Field; import java.util.*; public class ClientEventHandler { - - public static final RenderCNPCPlayer renderCNPCSelf = new RenderCNPCPlayer(); public static final RenderCNPCPlayer renderCNPCPlayer = new RenderCNPCPlayer(); public static HashMap disabledButtonTimes = new HashMap<>(); @@ -128,10 +126,7 @@ public class ClientEventHandler { @SubscribeEvent public void onRenderEntity(RenderLivingEvent.Post event) { - AnimationData data = null; if (event.entity instanceof EntityNPCInterface) { - data = ClientEventHandler.renderingNpc.display.animationData; - MarkData markData = MarkData.get((EntityNPCInterface) event.entity); EntityPlayer player = Minecraft.getMinecraft().thePlayer; if(PlayerData.get(player) != null){ @@ -143,10 +138,6 @@ public class ClientEventHandler { } } } else if (event.entity instanceof EntityPlayer) { - if (ClientCacheHandler.playerAnimations.containsKey(event.entity.getUniqueID())) { - data = ClientCacheHandler.playerAnimations.get(event.entity.getUniqueID()); - } - for (Map.Entry entry : ClientEventHandler.originalValues.entrySet()) { ModelRenderer renderer = entry.getKey(); FramePart part = entry.getValue(); @@ -161,35 +152,9 @@ public class ClientEventHandler { ClientEventHandler.playerModel = null; } - if (data != null && data.isActive() && !Minecraft.getMinecraft().isGamePaused()) { - Animation animation = data.animation; - if (data.isActive() && animation.currentFrame().useRenderTicks()) { - animation.increaseTime(); - } - } - ClientEventHandler.renderingNpc = null; } - @SubscribeEvent - public void onUpdateEntity(LivingEvent.LivingUpdateEvent event) { - if (FMLCommonHandler.instance().getEffectiveSide() == Side.CLIENT) { - AnimationData data = null; - if (event.entity instanceof EntityNPCInterface) { - data = ((EntityNPCInterface) event.entity).display.animationData; - } else if (event.entity instanceof EntityPlayer && ClientCacheHandler.playerAnimations.containsKey(event.entity.getUniqueID())) { - data = ClientCacheHandler.playerAnimations.get(event.entity.getUniqueID()); - } - - if (data != null && data.isActive()) { - Animation animation = data.animation; - if (data.isActive() && !animation.currentFrame().useRenderTicks()) { - animation.increaseTime(); - } - } - } - } - @SubscribeEvent public void onRenderPlayer(RenderPlayerEvent.Pre event) { ClientEventHandler.renderingPlayer = event.entityPlayer; diff --git a/src/main/java/noppes/npcs/client/ClientProxy.java b/src/main/java/noppes/npcs/client/ClientProxy.java index b13a75387..bd80d8532 100644 --- a/src/main/java/noppes/npcs/client/ClientProxy.java +++ b/src/main/java/noppes/npcs/client/ClientProxy.java @@ -80,6 +80,8 @@ public class ClientProxy extends CommonProxy { public static FontContainer Font; public void load() { + this.createAnimationThread(); + Font = new FontContainer(ConfigClient.FontType, ConfigClient.FontSize); createFolders(); CustomNpcs.Channel.register(new PacketHandlerClient()); diff --git a/src/main/java/noppes/npcs/client/gui/SubGuiAnimationFrame.java b/src/main/java/noppes/npcs/client/gui/SubGuiAnimationFrame.java index 89254ce2d..62837a495 100644 --- a/src/main/java/noppes/npcs/client/gui/SubGuiAnimationFrame.java +++ b/src/main/java/noppes/npcs/client/gui/SubGuiAnimationFrame.java @@ -10,7 +10,6 @@ public class SubGuiAnimationFrame extends SubGuiInterface implements ITextfieldL public SubGuiAnimationFrame(Frame editingFrame) { this.editingFrame = editingFrame; setBackground("smallbg.png"); - this.closeOnEsc = true; } @Override @@ -19,36 +18,42 @@ public class SubGuiAnimationFrame extends SubGuiInterface implements ITextfieldL // //customized - button, enables all the following options. this.addLabel(new GuiNpcLabel(10, "animation.customized", guiLeft + 5, guiTop + 16)); - this.addButton(new GuiNpcButton(10, guiLeft + 65, guiTop + 10, 30, 20, new String[]{"gui.yes", "gui.no"}, editingFrame.isCustomized() ? 0 : 1)); + this.addButton(new GuiNpcButton(10, guiLeft + 75, guiTop + 10, 30, 20, new String[]{"gui.yes", "gui.no"}, editingFrame.isCustomized() ? 0 : 1)); if (editingFrame.isCustomized()) { // //speed - textfield - this.addLabel(new GuiNpcLabel(11, "stats.speed", guiLeft + 5, guiTop + 36)); - this.addTextField(new GuiNpcTextField(11, this, guiLeft + 65, guiTop + 32, 30, 15, editingFrame.speed + "")); + this.addLabel(new GuiNpcLabel(11, "stats.speed", guiLeft + 5, guiTop + 42)); + this.addTextField(new GuiNpcTextField(11, this, guiLeft + 75, guiTop + 37, 30, 15, editingFrame.speed + "")); this.getTextField(11).floatsOnly = true; this.getTextField(11).setMinMaxDefaultFloat(0, Float.MAX_VALUE, 1.0F); // //smooth - button - this.addLabel(new GuiNpcLabel(12, "animation.smoothing", guiLeft + 5, guiTop + 58)); - this.addButton(new GuiNpcButton(12, guiLeft + 65, guiTop + 52, 60, 20, new String[]{"animation.smooth", "animation.linear", "gui.none"}, editingFrame.smooth)); + this.addLabel(new GuiNpcLabel(12, "animation.smoothing", guiLeft + 5, guiTop + 63)); + this.addButton(new GuiNpcButton(12, guiLeft + 75, guiTop + 55, 60, 20, new String[]{"animation.smooth", "animation.linear", "gui.none"}, editingFrame.smooth)); // - //ticks - button - this.addLabel(new GuiNpcLabel(13, "animation.tickType", guiLeft + 5, guiTop + 78)); - this.addButton(new GuiNpcButton(13, guiLeft + 65, guiTop + 72, 75, 20, new String[]{"animation.renderTicks", "animation.mcTicks"}, editingFrame.renderTicks ? 0 : 1)); + //tick duration - textfield + this.addLabel(new GuiNpcLabel(13, "animation.tickDuration", guiLeft + 5, guiTop + 84)); + this.addTextField(new GuiNpcTextField(13, this, guiLeft + 75, guiTop + 79, 40, 15, editingFrame.tickDuration + "")); + this.getTextField(13).integersOnly = true; + this.getTextField(13).setMinMaxDefault(1, Integer.MAX_VALUE, 50); } + + this.addLabel(new GuiNpcLabel(14, "Comment", guiLeft + 5, guiTop + 106)); + this.addTextField(new GuiNpcTextField(14, this, guiLeft + 50, guiTop + 101, 120, 15, editingFrame.getComment())); } @Override protected void actionPerformed(GuiButton guibutton) { super.actionPerformed(guibutton); - int value = ((GuiNpcButton)guibutton).getValue(); + if (this.editingFrame == null) { + return; + } - if (guibutton.id == 10 && editingFrame != null) { + int value = ((GuiNpcButton)guibutton).getValue(); + if (guibutton.id == 10) { editingFrame.setCustomized(!editingFrame.isCustomized()); - } else if (guibutton.id == 12 && editingFrame != null) { + } else if (guibutton.id == 12) { editingFrame.smooth = (byte) value; - } else if (guibutton.id == 13 && editingFrame != null) { - editingFrame.renderTicks = value == 0; } initGui(); @@ -56,8 +61,16 @@ public class SubGuiAnimationFrame extends SubGuiInterface implements ITextfieldL @Override public void unFocused(GuiNpcTextField textfield) { - if (textfield.id == 11 && this.editingFrame != null) { + if (this.editingFrame == null) { + return; + } + + if (textfield.id == 11) { this.editingFrame.speed = textfield.getFloat(); + } else if (textfield.id == 13) { + this.editingFrame.tickDuration = textfield.getInteger(); + } else if (textfield.id == 14) { + this.editingFrame.setComment(textfield.getText()); } } } diff --git a/src/main/java/noppes/npcs/client/gui/SubGuiAnimationOptions.java b/src/main/java/noppes/npcs/client/gui/SubGuiAnimationOptions.java index 5a021a406..1f3b7f0d1 100644 --- a/src/main/java/noppes/npcs/client/gui/SubGuiAnimationOptions.java +++ b/src/main/java/noppes/npcs/client/gui/SubGuiAnimationOptions.java @@ -1,18 +1,15 @@ package noppes.npcs.client.gui; import net.minecraft.client.gui.GuiButton; -import noppes.npcs.client.gui.util.GuiNpcButton; -import noppes.npcs.client.gui.util.GuiNpcLabel; -import noppes.npcs.client.gui.util.SubGuiInterface; +import noppes.npcs.client.gui.util.*; import noppes.npcs.controllers.data.Animation; -public class SubGuiAnimationOptions extends SubGuiInterface { +public class SubGuiAnimationOptions extends SubGuiInterface implements ITextfieldListener { private final Animation animation; public SubGuiAnimationOptions(Animation animation) { this.animation = animation; setBackground("smallbg.png"); - this.closeOnEsc = true; } @Override @@ -20,8 +17,10 @@ public class SubGuiAnimationOptions extends SubGuiInterface { super.initGui(); // //ticks - button - this.addLabel(new GuiNpcLabel(10, "animation.tickType", guiLeft + 5, guiTop + 16)); - this.addButton(new GuiNpcButton(10, guiLeft + 60, guiTop + 10, 75, 20, new String[]{"animation.renderTicks", "animation.mcTicks"}, animation.renderTicks ? 0 : 1)); + this.addLabel(new GuiNpcLabel(10, "animation.tickDuration", guiLeft + 5, guiTop + 16)); + this.addTextField(new GuiNpcTextField(10, this, guiLeft + 80, guiTop + 12, 40, 15, animation.tickDuration + "")); + this.getTextField(10).integersOnly = true; + this.getTextField(10).setMinMaxDefault(1, Integer.MAX_VALUE, 50); // //whileStanding - button this.addLabel(new GuiNpcLabel(11, "animation.whileStanding", guiLeft + 5, guiTop + 36)); @@ -41,9 +40,7 @@ public class SubGuiAnimationOptions extends SubGuiInterface { super.actionPerformed(guibutton); int value = ((GuiNpcButton)guibutton).getValue(); - if (guibutton.id == 10) { - animation.renderTicks = value == 0; - } else if (guibutton.id == 11) { + if (guibutton.id == 11) { animation.whileStanding = value == 0; } else if (guibutton.id == 12) { animation.whileAttacking = value == 0; @@ -53,4 +50,11 @@ public class SubGuiAnimationOptions extends SubGuiInterface { initGui(); } + + @Override + public void unFocused(GuiNpcTextField textfield) { + if (textfield.id == 10) { + animation.tickDuration = textfield.getInteger(); + } + } } diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiNPCEditAnimation.java b/src/main/java/noppes/npcs/client/gui/global/GuiNPCEditAnimation.java index 70c3a9470..73541f2d0 100644 --- a/src/main/java/noppes/npcs/client/gui/global/GuiNPCEditAnimation.java +++ b/src/main/java/noppes/npcs/client/gui/global/GuiNPCEditAnimation.java @@ -23,14 +23,16 @@ import java.util.Map; public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfieldListener, ISliderListener, ISubGuiListener { private final Animation animation; + private static int partEditMode; + private static int sliderSelection = 0; + private static Frame copiedFrame; + private EnumAnimationPart editingPart = EnumAnimationPart.HEAD; private int frameIndex = 0; public boolean playingAnimation = false; private Frame prevFrame; private final GuiScreen parent; private long prevTick; - private static int partEditMode; - private static int sliderSelection = 0; private final GuiNpcSlider[] rotationSliders = new GuiNpcSlider[3]; private final GuiNpcSlider[] pivotSliders = new GuiNpcSlider[3]; @@ -49,7 +51,7 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield this.animation = animation; AnimationData data = npc.display.animationData; - data.animation = animation; + data.setAnimation(animation); data.setEnabled(true); int bodyPartX = 280; @@ -92,9 +94,9 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield AnimationData data = npc.display.animationData; if (!playingAnimation) { - data.animation = new Animation(); + data.setAnimation(new Animation()); data.animation.smooth = animation.smooth; - data.animation.renderTicks = animation.renderTicks; + data.animation.tickDuration = 50; data.animation.loop = 0; if (editingFrame != null) { data.animation.frames.add(editingFrame); @@ -107,7 +109,7 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield if (!frame.isCustomized()) { frame.speed = animation.speed; frame.smooth = animation.smooth; - frame.renderTicks = animation.renderTicks; + frame.tickDuration = animation.tickDuration(); } for (Map.Entry entry : frame.frameParts.entrySet()) { FramePart part = entry.getValue(); @@ -401,13 +403,7 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield AnimationData data = npc.display.animationData; if (guibutton.id == 11) { - if (frameIndex < animation.frames.size() - 1) { - animation.frames.add(frameIndex + 1, new Frame(10)); - } else { - animation.frames.add(new Frame(10)); - } - this.frameIndex = frameIndex + 1; - updateFrameSlider(); + this.addFrame(); } else if (guibutton.id == 12) { animation.frames.remove(frameIndex); updateFrameSlider(); @@ -475,7 +471,7 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield } } this.playingAnimation = true; - data.animation = animation; + data.setAnimation(this.animation); data.animation.paused = false; } else if (guibutton.id == 201) { data.animation.paused = true; @@ -501,6 +497,20 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield initGui(); } + private void addFrame() { + this.addFrame(new Frame(10)); + } + + private void addFrame(Frame frame) { + if (frameIndex < animation.frames.size() - 1) { + animation.frames.add(frameIndex + 1, frame); + } else { + animation.frames.add(frame); + } + this.frameIndex = frameIndex + 1; + updateFrameSlider(); + } + @Override public void drawScreen(int par1, int par2, float par3) { @@ -510,12 +520,8 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield this.playingAnimation = false; initGui(); } else if (data.isActive()) { - Frame currentFrame = (Frame) data.animation.currentFrame(); long time = mc.theWorld.getTotalWorldTime(); if (time != prevTick) { - if (currentFrame != null && !currentFrame.renderTicks) { - data.animation.increaseTime(); - } GuiNpcLabel label = this.getLabel(213); if (label != null) { label.label += "."; @@ -533,8 +539,8 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield int sliderFrame = i + this.frameOffset; if (sliderFrame >= this.animation.frames.size()) { - button.color = 0x0; - button.alpha = 0.3F; + button.color = 0x0; + button.alpha = 0.3F; } else { button.color = this.animation.frames.get(sliderFrame).getColorMarker(); if ((sliderFrame == this.animation.currentFrame && this.playingAnimation) || sliderFrame == this.frameIndex) { @@ -643,4 +649,28 @@ public class GuiNPCEditAnimation extends GuiModelInterface implements ITextfield editingFrame.setColorMarker(((SubGuiColorSelector) subgui).color); } } + + @Override + public void keyTyped(char par1, int par2) { + super.keyTyped(par1, par2); + + if (GuiScreen.isCtrlKeyDown() && par2 != 29 && !GuiNpcTextField.isFieldActive()) { + switch (par2) { + case 46: + if (this.editingFrame() != null) { + copiedFrame = this.editingFrame(); + } + break; + case 47: + if (copiedFrame != null) { + Frame frame = new Frame(10); + frame.parent = this.animation; + frame.readFromNBT(copiedFrame.writeToNBT()); + this.addFrame(frame); + this.initGui(); + } + break; + } + } + } } diff --git a/src/main/java/noppes/npcs/client/gui/global/GuiNPCManageAnimations.java b/src/main/java/noppes/npcs/client/gui/global/GuiNPCManageAnimations.java index cbcdd0ed1..312e5a5e8 100644 --- a/src/main/java/noppes/npcs/client/gui/global/GuiNPCManageAnimations.java +++ b/src/main/java/noppes/npcs/client/gui/global/GuiNPCManageAnimations.java @@ -19,251 +19,247 @@ import java.util.Vector; public class GuiNPCManageAnimations extends GuiModelInterface2 implements IScrollData,ICustomScrollListener,ITextfieldListener, IGuiData, ISubGuiListener, GuiYesNoCallback { - private GuiCustomScroll scrollAnimations; - private HashMap data = new HashMap(); - private Animation animation = new Animation(); - public boolean playingAnimation = false; - private long prevTick; - private String selected = null; - private String search = ""; + private GuiCustomScroll scrollAnimations; + private HashMap data = new HashMap(); + private Animation animation = new Animation(); + public boolean playingAnimation = false; + private long prevTick; + private String selected = null; + private String search = ""; public GuiNPCManageAnimations(EntityNPCInterface npc, boolean save) { - super(npc); - this.setSave(save); - this.xOffset = -148 + 70; - this.yOffset = -170 + 137; - Client.sendData(EnumPacketServer.AnimationsGet); + super(npc); + this.setSave(save); + this.xOffset = -148 + 70; + this.yOffset = -170 + 137; + Client.sendData(EnumPacketServer.AnimationsGet); - AnimationData data = npc.display.animationData; - data.setEnabled(true); + AnimationData data = npc.display.animationData; + data.setEnabled(true); } public void initGui() { super.initGui(); - this.addButton(new GuiNpcButton(0,guiLeft + 368, guiTop + 8, 45, 20, "gui.add")); - this.addButton(new GuiNpcButton(1,guiLeft + 368, guiTop + 32, 45, 20, "gui.remove")); + this.addButton(new GuiNpcButton(0,guiLeft + 368, guiTop + 8, 45, 20, "gui.add")); + this.addButton(new GuiNpcButton(1,guiLeft + 368, guiTop + 32, 45, 20, "gui.remove")); - if(scrollAnimations == null){ - scrollAnimations = new GuiCustomScroll(this,0, 0); - scrollAnimations.setSize(143, 185); - } + if(scrollAnimations == null){ + scrollAnimations = new GuiCustomScroll(this,0, 0); + scrollAnimations.setSize(143, 185); + } scrollAnimations.guiLeft = guiLeft + 220; scrollAnimations.guiTop = guiTop + 4; - addScroll(scrollAnimations); - addTextField(new GuiNpcTextField(55, this, fontRendererObj, guiLeft + 220, guiTop + 192, 143, 20, search)); + addScroll(scrollAnimations); + addTextField(new GuiNpcTextField(55, this, fontRendererObj, guiLeft + 220, guiTop + 192, 143, 20, search)); - if (animation.id == -1) - return; + if (animation.id == -1) + return; - addLabel(new GuiNpcLabel(10,"ID", guiLeft + 368, guiTop + 192)); - addLabel(new GuiNpcLabel(11, animation.id + "", guiLeft + 368, guiTop + 192 + 10)); + addLabel(new GuiNpcLabel(10,"ID", guiLeft + 368, guiTop + 192)); + addLabel(new GuiNpcLabel(11, animation.id + "", guiLeft + 368, guiTop + 192 + 10)); - AnimationData data = npc.display.animationData; - if (!playingAnimation) { - data.animation = new Animation(); - data.animation.smooth = animation.smooth; - data.animation.renderTicks = animation.renderTicks; - data.animation.loop = 0; + AnimationData data = npc.display.animationData; + if (!playingAnimation) { + data.setAnimation(new Animation()); + data.animation.smooth = animation.smooth; + data.animation.tickDuration = 50; + data.animation.loop = 0; - if (this.animation.frames.size() > 0) { - Frame firstFrame = new Frame(); - firstFrame.parent = data.animation; - firstFrame.readFromNBT(this.animation.frames.get(0).writeToNBT()); - data.animation.addFrame(firstFrame); - } - } + if (this.animation.frames.size() > 0) { + Frame firstFrame = new Frame(); + firstFrame.parent = data.animation; + firstFrame.readFromNBT(this.animation.frames.get(0).writeToNBT()); + data.animation.addFrame(firstFrame); + } + } - if (animation != null) { - this.addButton(new GuiNpcButton(100, guiLeft + 10, guiTop + 192, 45, 20, "gui.edit")); - } + if (animation != null) { + this.addButton(new GuiNpcButton(100, guiLeft + 10, guiTop + 192, 45, 20, "gui.edit")); + } - String animTexture = "customnpcs:textures/gui/animation.png"; - int playButtonOffsetX = 140; - if (animation != null && !animation.frames.isEmpty()) { - if (!this.playingAnimation || data.animation.paused) {//Play - this.addLabel(new GuiNpcLabel(90, data.animation.paused ? "animation.paused" : "animation.stopped", guiLeft + playButtonOffsetX - 15, guiTop + 198)); - if (data.animation.paused) { - this.addLabel(new GuiNpcLabel(94, "", guiLeft + playButtonOffsetX + 21, guiTop + 198)); - } - this.addButton(new GuiTexturedButton(91, "", guiLeft + playButtonOffsetX + 35, guiTop + 192, 11, 20, animTexture, 18, 71)); - } else {//Pause - this.addLabel(new GuiNpcLabel(90, "animation.playing", guiLeft + playButtonOffsetX - 15, guiTop + 198)); - this.addLabel(new GuiNpcLabel(94, "", guiLeft + playButtonOffsetX + 20, guiTop + 198)); - this.addButton(new GuiTexturedButton(92, "", guiLeft + playButtonOffsetX + 35, guiTop + 192, 14, 20, animTexture, 0, 71)); - } - if (this.playingAnimation) {//Stop - this.addButton(new GuiTexturedButton(93, "", guiLeft + playButtonOffsetX + 55, guiTop + 192, 14, 20, animTexture, 33, 71)); - } - } + String animTexture = "customnpcs:textures/gui/animation.png"; + int playButtonOffsetX = 140; + if (animation != null && !animation.frames.isEmpty()) { + if (!this.playingAnimation || data.animation.paused) {//Play + this.addLabel(new GuiNpcLabel(90, data.animation.paused ? "animation.paused" : "animation.stopped", guiLeft + playButtonOffsetX - 15, guiTop + 198)); + if (data.animation.paused) { + this.addLabel(new GuiNpcLabel(94, "", guiLeft + playButtonOffsetX + 21, guiTop + 198)); + } + this.addButton(new GuiTexturedButton(91, "", guiLeft + playButtonOffsetX + 35, guiTop + 192, 11, 20, animTexture, 18, 71)); + } else {//Pause + this.addLabel(new GuiNpcLabel(90, "animation.playing", guiLeft + playButtonOffsetX - 15, guiTop + 198)); + this.addLabel(new GuiNpcLabel(94, "", guiLeft + playButtonOffsetX + 20, guiTop + 198)); + this.addButton(new GuiTexturedButton(92, "", guiLeft + playButtonOffsetX + 35, guiTop + 192, 14, 20, animTexture, 0, 71)); + } + if (this.playingAnimation) {//Stop + this.addButton(new GuiTexturedButton(93, "", guiLeft + playButtonOffsetX + 55, guiTop + 192, 14, 20, animTexture, 33, 71)); + } + } } - @Override - public void drawScreen(int par1, int par2, float par3) - { - super.drawScreen(par1,par2,par3); - AnimationData data = npc.display.animationData; - if (!data.isActive() && this.playingAnimation) { - this.playingAnimation = false; - initGui(); - } else if (data.isActive()) { - Frame currentFrame = (Frame) data.animation.currentFrame(); - long time = mc.theWorld.getTotalWorldTime(); - if (time != prevTick) { - if (currentFrame != null && !currentFrame.renderTicks) { - data.animation.increaseTime(); - } - GuiNpcLabel label = this.getLabel(94); - if (label != null) { - label.label += "."; - if (label.label.length()%4 == 0) { - label.label = ""; - } - } - } - prevTick = time; - } - } - - @Override - public void keyTyped(char c, int i) - { - super.keyTyped(c, i); - if(getTextField(55) != null){ - if(getTextField(55).isFocused()){ - if(search.equals(getTextField(55).getText())) - return; - search = getTextField(55).getText().toLowerCase(); - scrollAnimations.resetScroll(); - scrollAnimations.setList(getSearchList()); - } - } - } - - private List getSearchList(){ - if(search.isEmpty()){ - return new ArrayList(this.data.keySet()); - } - List list = new ArrayList(); - for(String name : this.data.keySet()){ - if(name.toLowerCase().contains(search)) - list.add(name); - } - return list; - } - @Override - protected void actionPerformed(GuiButton guibutton){ - GuiNpcButton button = (GuiNpcButton) guibutton; - - if(button.id == 0){ - save(); - String name = "New"; - while(data.containsKey(name)) - name += "_"; - Animation animation = new Animation(-1, name); - Client.sendData(EnumPacketServer.AnimationSave, animation.writeToNBT()); + public void drawScreen(int par1, int par2, float par3) + { + super.drawScreen(par1,par2,par3); + AnimationData data = npc.display.animationData; + if (!data.isActive() && this.playingAnimation) { + this.playingAnimation = false; + initGui(); + } else if (data.isActive()) { + long time = mc.theWorld.getTotalWorldTime(); + if (time != prevTick) { + GuiNpcLabel label = this.getLabel(94); + if (label != null) { + label.label += "."; + if (label.label.length()%4 == 0) { + label.label = ""; + } + } + } + prevTick = time; } - if(button.id == 1){ - if(data.containsKey(scrollAnimations.getSelected())) { - GuiYesNo guiyesno = new GuiYesNo(this, scrollAnimations.getSelected(), StatCollector.translateToLocal("gui.delete"), 1); - displayGuiScreen(guiyesno); - } - } - - AnimationData data = npc.display.animationData; - if (guibutton.id == 91) { - if (!this.playingAnimation || !data.isActive()) { - animation.currentFrame = 0; - animation.currentFrameTime = 0; - for (Frame frame : animation.frames) { - for (FramePart framePart : frame.frameParts.values()) { - framePart.prevRotations = new float[]{0,0,0}; - framePart.prevPivots = new float[]{0, 0, 0}; - } - } - } - this.playingAnimation = true; - data.animation = animation; - data.animation.paused = false; - } else if (guibutton.id == 92) { - data.animation.paused = true; - } else if (guibutton.id == 93) { - this.playingAnimation = false; - data.animation.paused = false; - } - - if (guibutton.id == 100) { - NoppesUtil.openGUI(player, new GuiNPCEditAnimation(this, this.animation, npc)); - } - - initGui(); } - @Override - public void setGuiData(NBTTagCompound compound) { - this.animation = new Animation(); - animation.readFromNBT(compound); - setSelected(animation.name); - npc.display.animationData.animation = animation; - this.playingAnimation = false; - npc.display.animationData.animation.paused = false; - initGui(); - } + @Override + public void keyTyped(char c, int i) + { + super.keyTyped(c, i); + if(getTextField(55) != null){ + if(getTextField(55).isFocused()){ + if(search.equals(getTextField(55).getText())) + return; + search = getTextField(55).getText().toLowerCase(); + scrollAnimations.resetScroll(); + scrollAnimations.setList(getSearchList()); + } + } + } - @Override - public void setData(Vector list, HashMap data) { - String name = scrollAnimations.getSelected(); - this.data = data; - scrollAnimations.setList(getSearchList()); + private List getSearchList(){ + if(search.isEmpty()){ + return new ArrayList(this.data.keySet()); + } + List list = new ArrayList(); + for(String name : this.data.keySet()){ + if(name.toLowerCase().contains(search)) + list.add(name); + } + return list; + } - if(name != null) - scrollAnimations.setSelected(name); - } + @Override + protected void actionPerformed(GuiButton guibutton){ + GuiNpcButton button = (GuiNpcButton) guibutton; - @Override - public void setSelected(String selected) { - this.selected = selected; - scrollAnimations.setSelected(selected); - } + if(button.id == 0){ + save(); + String name = "New"; + while(data.containsKey(name)) + name += "_"; + Animation animation = new Animation(-1, name); + Client.sendData(EnumPacketServer.AnimationSave, animation.writeToNBT()); + } + if(button.id == 1){ + if(data.containsKey(scrollAnimations.getSelected())) { + GuiYesNo guiyesno = new GuiYesNo(this, scrollAnimations.getSelected(), StatCollector.translateToLocal("gui.delete"), 1); + displayGuiScreen(guiyesno); + } + } - @Override - public void customScrollClicked(int i, int j, int k, GuiCustomScroll guiCustomScroll) { - if(guiCustomScroll.id == 0) - { - selected = scrollAnimations.getSelected(); - Client.sendData(EnumPacketServer.AnimationGet, data.get(selected)); - } - } + AnimationData data = npc.display.animationData; + if (guibutton.id == 91) { + if (!this.playingAnimation || !data.isActive()) { + animation.currentFrame = 0; + animation.currentFrameTime = 0; + for (Frame frame : animation.frames) { + for (FramePart framePart : frame.frameParts.values()) { + framePart.prevRotations = new float[]{0,0,0}; + framePart.prevPivots = new float[]{0, 0, 0}; + } + } + } + this.playingAnimation = true; + data.setAnimation(this.animation); + data.animation.paused = false; + } else if (guibutton.id == 92) { + data.animation.paused = true; + } else if (guibutton.id == 93) { + this.playingAnimation = false; + data.animation.paused = false; + } - public void save() { - if(selected != null && data.containsKey(selected) && animation != null){ - Client.sendData(EnumPacketServer.AnimationSave, animation.writeToNBT()); - } - } + if (guibutton.id == 100) { + NoppesUtil.openGUI(player, new GuiNPCEditAnimation(this, this.animation, npc)); + } - @Override - public void unFocused(GuiNpcTextField guiNpcTextField) { - if(animation.id == -1) - return; + initGui(); + } - if(guiNpcTextField.id == 0) { - String name = guiNpcTextField.getText(); - if(!name.isEmpty() && !data.containsKey(name)){ - String old = animation.name; - data.remove(animation.name); - animation.name = name; - data.put(animation.name, animation.id); - selected = name; - scrollAnimations.replace(old, animation.name); - } - } - } + @Override + public void setGuiData(NBTTagCompound compound) { + this.animation = new Animation(); + animation.readFromNBT(compound); + setSelected(animation.name); + npc.display.animationData.setAnimation(this.animation); + this.playingAnimation = false; + npc.display.animationData.animation.paused = false; + initGui(); + } - @Override - public void subGuiClosed(SubGuiInterface subgui) {} + @Override + public void setData(Vector list, HashMap data) { + String name = scrollAnimations.getSelected(); + this.data = data; + scrollAnimations.setList(getSearchList()); + + if(name != null) + scrollAnimations.setSelected(name); + } + + @Override + public void setSelected(String selected) { + this.selected = selected; + scrollAnimations.setSelected(selected); + } + + @Override + public void customScrollClicked(int i, int j, int k, GuiCustomScroll guiCustomScroll) { + if(guiCustomScroll.id == 0) + { + selected = scrollAnimations.getSelected(); + Client.sendData(EnumPacketServer.AnimationGet, data.get(selected)); + } + } + + public void save() { + if(selected != null && data.containsKey(selected) && animation != null){ + Client.sendData(EnumPacketServer.AnimationSave, animation.writeToNBT()); + } + } + + @Override + public void unFocused(GuiNpcTextField guiNpcTextField) { + if(animation.id == -1) + return; + + if(guiNpcTextField.id == 0) { + String name = guiNpcTextField.getText(); + if(!name.isEmpty() && !data.containsKey(name)){ + String old = animation.name; + data.remove(animation.name); + animation.name = name; + data.put(animation.name, animation.id); + selected = name; + scrollAnimations.replace(old, animation.name); + } + } + } + + @Override + public void subGuiClosed(SubGuiInterface subgui) {} @Override public void confirmClicked(boolean result, int id) { 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 3f2774fe3..3ea6f6dee 100644 --- a/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java +++ b/src/main/java/noppes/npcs/client/gui/script/GuiScriptPlayers.java @@ -73,6 +73,10 @@ public class GuiScriptPlayers extends GuiScriptInterface { hookList.add("partyKick"); hookList.add("partyLeave"); hookList.add("partyDisband"); + hookList.add("animationStart"); + hookList.add("animationEnd"); + hookList.add("frameEnter"); + hookList.add("frameExit"); this.handler = this.script; Client.sendData(EnumPacketServer.ScriptPlayerGet); diff --git a/src/main/java/noppes/npcs/controllers/data/Animation.java b/src/main/java/noppes/npcs/controllers/data/Animation.java index 569ff7614..c8eeaace9 100644 --- a/src/main/java/noppes/npcs/controllers/data/Animation.java +++ b/src/main/java/noppes/npcs/controllers/data/Animation.java @@ -4,7 +4,9 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; +import noppes.npcs.EventHooks; import noppes.npcs.api.handler.data.IAnimation; +import noppes.npcs.api.handler.data.IAnimationData; import noppes.npcs.api.handler.data.IFrame; import noppes.npcs.constants.EnumAnimationPart; import noppes.npcs.controllers.AnimationController; @@ -13,262 +15,300 @@ import java.util.ArrayList; public class Animation implements IAnimation { - public AnimationData parent; //Client-sided only - public int id = -1; // Only for internal usage + public AnimationData parent; //Client-sided only + public int id = -1; // Only for internal usage - public ArrayList frames = new ArrayList<>(); - public int currentFrame = 0; - public int currentFrameTime = 0; + public ArrayList frames = new ArrayList<>(); + public int currentFrame = 0; + public int currentFrameTime = 0; - public String name = ""; - public float speed = 1.0F; - public byte smooth = 0; - public int loop = -1; //If greater than 0 and less than the amount of frames, the animation will begin looping when it reaches this frame. - public boolean renderTicks = false; // If true, MC ticks are used. If false, render ticks are used. + public String name = ""; + public float speed = 1.0F; + public byte smooth = 0; + public int loop = -1; //If greater than 0 and less than the amount of frames, the animation will begin looping when it reaches this frame. + public int tickDuration = 50; - public boolean whileStanding = true; - public boolean whileAttacking = true; - public boolean whileMoving = true; + public boolean whileStanding = true; + public boolean whileAttacking = true; + public boolean whileMoving = true; - //Client-sided - public boolean paused; + //Client-sided + public boolean paused; - public Animation(){} + public Animation(){} - public Animation(int id, String name){ - this.name = name; - this.id = id; - } + public Animation(int id, String name){ + this.name = name; + this.id = id; + } - public Animation(int id, String name, float speed, byte smooth){ - this.name = name; - this.speed = speed; - this.smooth = smooth; + public Animation(int id, String name, float speed, byte smooth){ + this.name = name; + this.speed = speed; + this.smooth = smooth; - this.id = id; - } + this.id = id; + } - public IFrame currentFrame() { - return currentFrame < frames.size() ? frames.get(currentFrame) : null; - } + public IAnimationData getParent() { + return this.parent; + } - public IFrame[] getFrames() { - return frames.toArray(new Frame[0]); - } + public IFrame currentFrame() { + return currentFrame < frames.size() ? frames.get(currentFrame) : null; + } - public IAnimation setFrames(IFrame[] frames) { - this.clearFrames(); - for (IFrame frame : frames) { - this.frames.add((Frame) frame); - } - return this; - } + public IFrame[] getFrames() { + return frames.toArray(new Frame[0]); + } - public IAnimation clearFrames() { - this.frames.clear(); - return this; - } + public IAnimation setFrames(IFrame[] frames) { + this.clearFrames(); + for (IFrame frame : frames) { + this.frames.add((Frame) frame); + } + return this; + } - public IAnimation addFrame(IFrame frame) { - this.frames.add((Frame) frame); - return this; - } + public IAnimation clearFrames() { + this.frames.clear(); + return this; + } - public IAnimation addFrame(int index, IFrame frame) { - this.frames.add(index, (Frame) frame); - return this; - } + public IAnimation addFrame(IFrame frame) { + this.frames.add((Frame) frame); + return this; + } - public IAnimation removeFrame(IFrame frame) { - this.frames.remove((Frame) frame); - return this; - } + public IAnimation addFrame(int index, IFrame frame) { + this.frames.add(index, (Frame) frame); + return this; + } - public IAnimation setName(String name) { - this.name = name; - return this; - } + public IAnimation removeFrame(IFrame frame) { + this.frames.remove((Frame) frame); + return this; + } - public String getName() { - return this.name; - } + public IAnimation setName(String name) { + this.name = name; + return this; + } - public IAnimation setSpeed(float speed) { - this.speed = speed; - return this; - } + public String getName() { + return this.name; + } - public float getSpeed() { - return this.speed; - } + public int tickDuration() { + return this.tickDuration; + } - public IAnimation setSmooth(byte smooth) { - this.smooth = smooth; - return this; - } + public IAnimation setTickDuration(int tickDuration) { + this.tickDuration = tickDuration; + return this; + } - public byte isSmooth() { - return this.smooth; - } + public IAnimation setSpeed(float speed) { + this.speed = speed; + return this; + } - public IAnimation useRenderTicks(boolean renderTicks) { - this.renderTicks = renderTicks; - return this; - } + public float getSpeed() { + return this.speed; + } - public boolean useRenderTicks() { - return this.renderTicks; - } + public IAnimation setSmooth(byte smooth) { + this.smooth = smooth; + return this; + } - public IAnimation doWhileStanding(boolean whileStanding) { - this.whileStanding = whileStanding; - return this; - } + public byte isSmooth() { + return this.smooth; + } - public boolean doWhileStanding() { - return this.whileStanding; - } + public IAnimation doWhileStanding(boolean whileStanding) { + this.whileStanding = whileStanding; + return this; + } - public IAnimation doWhileMoving(boolean whileMoving) { - this.whileMoving = whileMoving; - return this; - } + public boolean doWhileStanding() { + return this.whileStanding; + } - public boolean doWhileMoving() { - return this.whileMoving; - } + public IAnimation doWhileMoving(boolean whileMoving) { + this.whileMoving = whileMoving; + return this; + } - public IAnimation doWhileAttacking(boolean whileAttacking) { - this.whileAttacking = whileAttacking; - return this; - } + public boolean doWhileMoving() { + return this.whileMoving; + } - public boolean doWhileAttacking() { - return this.whileAttacking; - } + public IAnimation doWhileAttacking(boolean whileAttacking) { + this.whileAttacking = whileAttacking; + return this; + } - public IAnimation setLoop(int loopAtFrame) { - this.loop = loopAtFrame; - return this; - } + public boolean doWhileAttacking() { + return this.whileAttacking; + } - public int loop() { - return this.loop; - } + public IAnimation setLoop(int loopAtFrame) { + this.loop = loopAtFrame; + return this; + } - public IAnimation save() { - return AnimationController.Instance.saveAnimation(this); - } + public int loop() { + return this.loop; + } - @Override - public int getID() { - return id; - } + public IAnimation save() { + return AnimationController.Instance.saveAnimation(this); + } - @Override - public void setID(int newID) { - id = newID; - } + @Override + public int getID() { + return id; + } - public void readFromNBT(NBTTagCompound compound){ - if(compound.hasKey("ID")){ - id = compound.getInteger("ID"); - } - else if (AnimationController.Instance != null) { - id = AnimationController.Instance.getUnusedId(); - } + @Override + public void setID(int newID) { + id = newID; + } - name = compound.getString("Name"); - speed = compound.getFloat("Speed"); - smooth = compound.getByte("Smooth"); - loop = compound.getInteger("Loop"); + public long getTotalTime() { + long time = 0; + for (Frame frame : this.frames) { + time += (long) frame.duration * (frame.customized ? frame.tickDuration : this.tickDuration); + } + return time; + } - renderTicks = compound.getBoolean("RenderTicks"); + public void readFromNBT(NBTTagCompound compound){ + if(compound.hasKey("ID")){ + id = compound.getInteger("ID"); + } + else if (AnimationController.Instance != null) { + id = AnimationController.Instance.getUnusedId(); + } - ArrayList frames = new ArrayList(); - NBTTagList list = compound.getTagList("Frames", 10); - for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound item = list.getCompoundTagAt(i); - Frame frame = new Frame(); - frame.parent = this; - frame.readFromNBT(item); - frames.add(frame); - } - this.frames = frames; + name = compound.getString("Name"); + speed = compound.getFloat("Speed"); + smooth = compound.getByte("Smooth"); + loop = compound.getInteger("Loop"); - this.whileStanding = compound.getBoolean("WhileStanding"); - this.whileMoving = compound.getBoolean("WhileWalking"); - this.whileAttacking = compound.getBoolean("WhileAttacking"); - } + if (compound.hasKey("TickDuration")) { + this.tickDuration = compound.getInteger("TickDuration"); + } else if(compound.hasKey("RenderTicks")){ + this.tickDuration = compound.getBoolean("RenderTicks") ? 20 : 50; + } - public NBTTagCompound writeToNBT(){ - NBTTagCompound compound = new NBTTagCompound(); - compound.setInteger("ID", id); - compound.setString("Name", name); - compound.setFloat("Speed", speed); - compound.setByte("Smooth", smooth); - compound.setInteger("Loop",loop); + ArrayList frames = new ArrayList(); + NBTTagList list = compound.getTagList("Frames", 10); + for (int i = 0; i < list.tagCount(); i++) { + NBTTagCompound item = list.getCompoundTagAt(i); + Frame frame = new Frame(); + frame.parent = this; + frame.readFromNBT(item); + frames.add(frame); + } + this.frames = frames; - compound.setBoolean("RenderTicks", renderTicks); + this.whileStanding = compound.getBoolean("WhileStanding"); + this.whileMoving = compound.getBoolean("WhileWalking"); + this.whileAttacking = compound.getBoolean("WhileAttacking"); - NBTTagList list = new NBTTagList(); - for(Frame frame : frames){ - NBTTagCompound item = frame.writeToNBT(); - list.appendTag(item); - } - compound.setTag("Frames", list); + this.currentFrame = compound.getInteger("CurrentFrame"); + this.currentFrameTime = compound.getInteger("CurrentFrameTime"); + } - compound.setBoolean("WhileStanding", whileStanding); - compound.setBoolean("WhileWalking", whileMoving); - compound.setBoolean("WhileAttacking", whileAttacking); - return compound; - } + public NBTTagCompound writeToNBT(){ + NBTTagCompound compound = new NBTTagCompound(); + compound.setInteger("ID", id); + compound.setString("Name", name); + compound.setFloat("Speed", speed); + compound.setByte("Smooth", smooth); + compound.setInteger("Loop",loop); + compound.setInteger("TickDuration", tickDuration); - @SideOnly(Side.CLIENT) - public void increaseTime() { - if (paused) - return; + NBTTagList list = new NBTTagList(); + for(Frame frame : frames){ + NBTTagCompound item = frame.writeToNBT(); + list.appendTag(item); + } + compound.setTag("Frames", list); - if (this.parent != null && this.currentFrame < this.frames.size()) { - this.parent.finishedFrame = this.currentFrame; - } + compound.setBoolean("WhileStanding", whileStanding); + compound.setBoolean("WhileWalking", whileMoving); + compound.setBoolean("WhileAttacking", whileAttacking); - this.currentFrameTime++; - if (this.currentFrameTime == this.currentFrame().getDuration()) { - Frame prevFrame = (Frame) this.currentFrame(); - Frame nextFrame = null; - this.currentFrameTime = 0; - this.currentFrame++; - if (this.currentFrame < this.frames.size()) { - nextFrame = this.frames.get(this.currentFrame); - } else if (this.loop >= 0 && this.loop < this.frames.size()) { - this.currentFrame = this.loop; - } - if (nextFrame != null) { - for (EnumAnimationPart part : EnumAnimationPart.values()) { - if (prevFrame.frameParts.containsKey(part) && nextFrame.frameParts.containsKey(part)) { - nextFrame.frameParts.get(part).prevRotations = prevFrame.frameParts.get(part).prevRotations; - nextFrame.frameParts.get(part).prevPivots = prevFrame.frameParts.get(part).prevPivots; - } - } - } else if (this.parent != null && this.currentFrame > this.loop) { - this.parent.finishedTime = this.parent.animationEntity.getAge(); - } - } - } + compound.setInteger("CurrentFrame", currentFrame); + compound.setInteger("CurrentFrameTime", currentFrameTime); + return compound; + } - @SideOnly(Side.CLIENT) - public void jumpToCurrentFrame() { - this.currentFrameTime = 0; - Frame frame = (Frame) this.currentFrame(); - if(frame != null){ - for (EnumAnimationPart part : EnumAnimationPart.values()) { - if(part != null){ - if (frame.frameParts.containsKey(part)) { - frame.frameParts.get(part).jumpToCurrentFrame(); - } - } - } - } - } + public boolean increaseTime() { + if (paused) + return false; + + if (this.parent != null && this.currentFrame < this.frames.size()) { + this.parent.finishedFrame = this.currentFrame; + } + + this.currentFrameTime++; + if (this.currentFrame() != null && this.currentFrameTime == this.currentFrame().getDuration()) { + EventHooks.onAnimationFrameExited(this, this.currentFrame()); + + Frame prevFrame = (Frame) this.currentFrame(); + Frame nextFrame = null; + this.currentFrameTime = 0; + this.currentFrame++; + if (this.currentFrame < this.frames.size()) { + nextFrame = this.frames.get(this.currentFrame); + } else if (this.loop >= 0 && this.loop < this.frames.size()) { + this.currentFrame = this.loop; + } + + if (this.currentFrame() != null) { + EventHooks.onAnimationFrameEntered(this, this.currentFrame()); + } else { + EventHooks.onAnimationEnded(this); + } + + if (nextFrame != null) { + for (EnumAnimationPart part : EnumAnimationPart.values()) { + if (prevFrame.frameParts.containsKey(part) && nextFrame.frameParts.containsKey(part)) { + nextFrame.frameParts.get(part).prevRotations = prevFrame.frameParts.get(part).prevRotations; + nextFrame.frameParts.get(part).prevPivots = prevFrame.frameParts.get(part).prevPivots; + } + } + } else if (this.parent != null && this.currentFrame > this.loop) { + this.parent.finishedTime = this.parent.getMCEntity().getAge(); + } + } + + return true; + } + + @SideOnly(Side.CLIENT) + public void jumpToCurrentFrame() { + this.jumpToFrameAtTime(this.currentFrame, 0); + } + + @SideOnly(Side.CLIENT) + public void jumpToFrameAtTime(int frameIndex, int time) { + this.currentFrame = frameIndex; + this.currentFrameTime = time; + + Frame frame = (Frame) this.currentFrame(); + if(frame != null){ + for (EnumAnimationPart part : EnumAnimationPart.values()) { + if(part != null){ + if (frame.frameParts.containsKey(part)) { + frame.frameParts.get(part).jumpToCurrentFrame(); + } + } + } + } + } } diff --git a/src/main/java/noppes/npcs/controllers/data/AnimationData.java b/src/main/java/noppes/npcs/controllers/data/AnimationData.java index 4c47c9e5e..8ddf852ce 100644 --- a/src/main/java/noppes/npcs/controllers/data/AnimationData.java +++ b/src/main/java/noppes/npcs/controllers/data/AnimationData.java @@ -3,19 +3,25 @@ package noppes.npcs.controllers.data; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.relauncher.Side; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.AxisAlignedBB; +import noppes.npcs.CommonProxy; import noppes.npcs.DataDisplay; +import noppes.npcs.EventHooks; import noppes.npcs.Server; +import noppes.npcs.api.entity.IAnimatable; +import noppes.npcs.api.entity.IEntity; import noppes.npcs.api.handler.data.IAnimation; import noppes.npcs.api.handler.data.IAnimationData; import noppes.npcs.constants.EnumAnimationPart; import noppes.npcs.constants.EnumPacketClient; import noppes.npcs.controllers.PlayerDataController; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.scripted.NpcAPI; import java.util.Arrays; import java.util.HashSet; @@ -29,20 +35,47 @@ public class AnimationData implements IAnimationData { public Animation animation; public boolean allowAnimation = false; + public long animatingTime = 0; + + public Animation currentClientAnimation; + private boolean isClientAnimating; private final HashSet cachedAnimationIDs = new HashSet<>(); //Client-side values - public EntityLivingBase animationEntity; public int finishedTime = -1; public int finishedFrame = -1; public AnimationData(Object parent){ this.parent = parent; - if (parent instanceof DataDisplay) { - this.animationEntity = ((DataDisplay) parent).npc; - } else if (parent instanceof EntityPlayer) { - this.animationEntity = (EntityLivingBase) parent; + } + public static AnimationData getData(Entity entity) { + if (entity instanceof EntityPlayerMP) { + return PlayerData.get((EntityPlayer) entity).animationData; + } else if (entity instanceof EntityNPCInterface) { + return ((EntityNPCInterface)entity).display.animationData; + } else { + return null; + } + } + + public IAnimatable getEntity() { + IEntity entity = NpcAPI.Instance().getIEntity(this.getMCEntity()); + if (entity instanceof IAnimatable) { + return (IAnimatable) entity; + } + return null; + } + + public EntityLivingBase getMCEntity() { + if (this.parent instanceof DataDisplay) { + return ((DataDisplay) this.parent).npc; + } else { + if (this.parent instanceof PlayerData) { + return ((PlayerData) this.parent).player; + } else { + return (EntityPlayer) this.parent; + } } } @@ -57,6 +90,30 @@ public class AnimationData implements IAnimationData { if(sendingEntity.dimension != sendingEntity.worldObj.provider.dimensionId) sendingEntity.dimension = sendingEntity.worldObj.provider.dimensionId; + this.animatingTime = 0; + + boolean prevIsClientAnimating = this.isClientAnimating && this.currentClientAnimation.currentFrame() != null; + this.isClientAnimating = this.allowAnimation && this.animation != null; + if (prevIsClientAnimating && (!this.isClientAnimating || this.animation != this.currentClientAnimation)) { + EventHooks.onAnimationEnded(this.currentClientAnimation); + } + if (this.isClientAnimating) { + this.currentClientAnimation = this.animation; + } + + if (this.animation != null && this.allowAnimation) { + if (EventHooks.onAnimationStarted(this.animation)) + return; + EventHooks.onAnimationFrameEntered(this.animation, this.animation.currentFrame()); + } + + synchronized (CommonProxy.serverPlayingAnimations) { + if (this.isClientAnimating && this.getMCEntity() != null && + !this.getMCEntity().worldObj.isRemote && this.animation != null) { + CommonProxy.serverPlayingAnimations.add(this); + } + } + List entities = sendingEntity.worldObj.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getBoundingBox( sendingEntity.posX - range, sendingEntity.posY - range, sendingEntity.posZ - range, sendingEntity.posX + range, sendingEntity.posY + range, sendingEntity.posZ + range)); @@ -69,13 +126,21 @@ public class AnimationData implements IAnimationData { if (animationNBT == null && this.animation != null && !animationData.isCached(this.animation.getID())) { animationNBT = this.animation.writeToNBT(); } - animationData.viewAnimation(this.animation, sendingEntity, this, animationNBT); + animationData.viewAnimation(this.animation, this, animationNBT); } } } + public boolean isClientAnimating() { + return this.isClientAnimating; + } + public boolean isActive() { - if (!this.allowAnimation || this.animation == null || this.animation.currentFrame == this.animation.frames.size() || animation.currentFrame() == null) + return this.isActive(this.animation); + } + + public boolean isActive(Animation animation) { + if (!this.allowAnimation || animation == null || animation.currentFrame == animation.frames.size() || animation.currentFrame() == null) return false; if (this.parent instanceof DataDisplay) { @@ -100,6 +165,25 @@ public class AnimationData implements IAnimationData { } } + public void increaseTime() { + Animation updateAnimation = null; + if (this.isActive(animation.parent.currentClientAnimation)) { + updateAnimation = this.currentClientAnimation; + } else { + this.isClientAnimating = false; + if (this.isActive()) { + updateAnimation = this.animation; + } + } + + if (updateAnimation != null && updateAnimation.increaseTime()) { + Frame frame = (Frame) updateAnimation.currentFrame(); + if (frame != null) { + this.animatingTime += frame.customized ? frame.tickDuration : updateAnimation.tickDuration; + } + } + } + public boolean isCached(int id) { return this.cachedAnimationIDs.contains(id); } @@ -116,27 +200,77 @@ public class AnimationData implements IAnimationData { this.cachedAnimationIDs.clear(); } - public void viewAnimation(Animation animation, EntityLivingBase entity, AnimationData animationData, NBTTagCompound animationNBT) { - NBTTagCompound data = animationData.writeToNBT(new NBTTagCompound()); + public void viewAnimation(Animation animation, AnimationData animationData, NBTTagCompound animationNBT) { + this.viewAnimation(animation, animationData, animationNBT, animationData.allowAnimation, -1, -1); + } + + public boolean viewAnimation(Animation animation, AnimationData animationData, NBTTagCompound animationNBT, boolean enabled, int currentFrame, int time) { + if (animation != null + && (currentFrame >= animation.frames.size() + || currentFrame >= 0 && animation.frames.get(currentFrame).getDuration() < time)) { + return false; + } + + boolean prevEnabled = animationData.allowAnimation; + animationData.allowAnimation = enabled; + NBTTagCompound data = animationData.viewWriteNBT(new NBTTagCompound()); + animationData.allowAnimation = prevEnabled; + + if (animation != null && currentFrame >= 0 && currentFrame < animation.frames.size()) { + data.setInteger("Frame", currentFrame); + data.setInteger("Time", time); + } + if (animation != null) { - if (this.cachedAnimationIDs.contains(animation.getID())) { + if (this.cachedAnimationIDs.contains(animation.getID()) && !data.hasKey("Frame")) { data.setInteger("AnimationID", animation.getID()); } else { data.setTag("Animation", animationNBT); } } + + IAnimatable animatable = animationData.getEntity(); + Entity entity = ((IEntity) animatable).getMCEntity(); if (!(entity instanceof EntityPlayer)) { data.setInteger("EntityId", entity.getEntityId()); } + Server.sendData((EntityPlayerMP) ((PlayerData) parent).player, EnumPacketClient.UPDATE_ANIMATIONS, data, entity.getCommandSenderName()); + return true; + } + + public NBTTagCompound viewWriteNBT(NBTTagCompound compound) { + compound.setBoolean("AllowAnimation", allowAnimation); + return compound; + } + + public void viewReadFromNBT(NBTTagCompound compound) { + this.setEnabled(compound.getBoolean("AllowAnimation")); } public NBTTagCompound writeToNBT(NBTTagCompound compound) { + if (this.currentClientAnimation != null) { + compound.setBoolean("IsClientAnimating", isClientAnimating); + if (this.isClientAnimating) { + compound.setTag("CurrentAnimation", currentClientAnimation.writeToNBT()); + } + } compound.setBoolean("AllowAnimation", allowAnimation); return compound; } public void readFromNBT(NBTTagCompound compound) { + Entity entity = this.getMCEntity(); + boolean isServer = entity != null && !entity.worldObj.isRemote; + if (compound.hasKey("IsClientAnimating") && isServer) { + this.isClientAnimating = compound.getBoolean("IsClientAnimating"); + if (this.isClientAnimating) { + this.currentClientAnimation = new Animation(); + this.currentClientAnimation.parent = this; + this.currentClientAnimation.readFromNBT(compound.getCompoundTag("CurrentAnimation")); + this.animation = this.currentClientAnimation; + } + } this.setEnabled(compound.getBoolean("AllowAnimation")); } @@ -154,32 +288,41 @@ public class AnimationData implements IAnimationData { } public void setAnimation(IAnimation animation) { - if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { - this.animation = animation != null ? (Animation) animation : null; - } else { - if (animation != null) { - Animation newAnim = new Animation(); - newAnim.readFromNBT(((Animation) animation).writeToNBT()); - if (this.isActive() && !newAnim.frames.isEmpty()) { - Frame frame = (Frame) this.animation.currentFrame(); - if (frame != null) { - Frame firstFrame = newAnim.frames.get(0); - for (Map.Entry entry : frame.frameParts.entrySet()) { - if (firstFrame.frameParts.containsKey(entry.getKey())) { - FramePart prevFramePart = entry.getValue(); - FramePart newFramePart = firstFrame.frameParts.get(entry.getKey()); - for (int i = 0; i < 3; i++) { - newFramePart.prevPivots[i] = prevFramePart.prevPivots[i]; - newFramePart.prevRotations[i] = prevFramePart.prevRotations[i]; - } - } + Animation newAnim = null; + if (animation != null) { + newAnim = new Animation(); + newAnim.readFromNBT(((Animation) animation).writeToNBT()); + newAnim.currentFrame = 0; + newAnim.currentFrameTime = 0; + newAnim.parent = this; + } + + + if (this.getMCEntity() != null && this.getMCEntity().worldObj.isRemote && newAnim != null) { + this.animatingTime = 0; + synchronized (CommonProxy.clientPlayingAnimations) { + CommonProxy.clientPlayingAnimations.add(this); + } + } + + Animation prevAnim = this.animation; + this.animation = newAnim; + + if (this.getMCEntity() != null && this.getMCEntity().worldObj.isRemote && + this.isActive() && prevAnim != null && newAnim != null && !newAnim.frames.isEmpty()) { + Frame frame = (Frame) prevAnim.currentFrame(); + if (frame != null) { + Frame firstFrame = newAnim.frames.get(0); + for (Map.Entry entry : frame.frameParts.entrySet()) { + if (firstFrame.frameParts.containsKey(entry.getKey())) { + FramePart prevFramePart = entry.getValue(); + FramePart newFramePart = firstFrame.frameParts.get(entry.getKey()); + for (int i = 0; i < 3; i++) { + newFramePart.prevPivots[i] = prevFramePart.prevPivots[i]; + newFramePart.prevRotations[i] = prevFramePart.prevRotations[i]; } } } - this.animation = newAnim; - newAnim.parent = this; - } else { - this.animation = null; } } } @@ -187,4 +330,8 @@ public class AnimationData implements IAnimationData { public IAnimation getAnimation() { return animation; } + + public long getAnimatingTime() { + return this.animatingTime; + } } diff --git a/src/main/java/noppes/npcs/controllers/data/Frame.java b/src/main/java/noppes/npcs/controllers/data/Frame.java index df80096bd..770ba924c 100644 --- a/src/main/java/noppes/npcs/controllers/data/Frame.java +++ b/src/main/java/noppes/npcs/controllers/data/Frame.java @@ -11,188 +11,206 @@ import java.util.Map; public class Frame implements IFrame { - public Animation parent; - public HashMap frameParts = new HashMap<>(); - public int duration = 0; - boolean customized = false; - public float speed = 1.0F; - public byte smooth = 0; - public boolean renderTicks = false; // If true, MC ticks are used. If false, render ticks are used. + public Animation parent; + public HashMap frameParts = new HashMap<>(); + public int duration = 0; + public int tickDuration = 50; - private int colorMarker = 0xFFFFFF; + boolean customized = false; + public float speed = 1.0F; + public byte smooth = 0; - public Frame(){} + private int colorMarker = 0xFFFFFF; + private String comment = ""; - public Frame(int duration) { - this.duration = duration; - } + public Frame(){} - public Frame(int duration, float speed, byte smooth) { - this.duration = duration; - this.speed = speed; - this.smooth = smooth; - this.customized = true; - } + public Frame(int duration) { + this.duration = duration; + } - public HashMap getFrameMap() { - return frameParts; - } + public Frame(int duration, float speed, byte smooth) { + this.duration = duration; + this.speed = speed; + this.smooth = smooth; + this.customized = true; + } - public IFramePart[] getParts() { - return frameParts.values().toArray(new IFramePart[0]); - } + public HashMap getFrameMap() { + return frameParts; + } - public IFrame addPart(IFramePart partConfig) { - this.frameParts.put(((FramePart)partConfig).getPart(),(FramePart) partConfig); - return this; - } + public IFramePart[] getParts() { + return frameParts.values().toArray(new IFramePart[0]); + } - public IFrame removePart(String partName) { - try { - this.frameParts.remove(EnumAnimationPart.valueOf(partName)); - } catch (IllegalArgumentException ignored) {} - return this; - } + public IFrame addPart(IFramePart partConfig) { + this.frameParts.put(((FramePart)partConfig).getPart(),(FramePart) partConfig); + return this; + } - public IFrame removePart(int partId) { - for (EnumAnimationPart part : EnumAnimationPart.values()) { - this.frameParts.remove(part); - } - return this; - } + public IFrame removePart(String partName) { + try { + this.frameParts.remove(EnumAnimationPart.valueOf(partName)); + } catch (IllegalArgumentException ignored) {} + return this; + } - public IFrame clearParts() { - frameParts.clear(); - return this; - } + public IFrame removePart(int partId) { + for (EnumAnimationPart part : EnumAnimationPart.values()) { + this.frameParts.remove(part); + } + return this; + } - public int getDuration() { - return duration; - } + public IFrame clearParts() { + frameParts.clear(); + return this; + } - public IFrame setDuration(int duration) { - this.duration = duration; - return this; - } + public int getDuration() { + return duration; + } - public boolean isCustomized() { - return customized; - } + public IFrame setDuration(int duration) { + this.duration = duration; + return this; + } - public IFrame setCustomized(boolean customized) { - this.customized = customized; - return this; - } + public int tickDuration() { + return !this.customized && this.parent != null ? this.parent.tickDuration : this.tickDuration; + } - public float getSpeed() { - return speed; - } + public IFrame setTickDuration(int tickDuration) { + this.tickDuration = tickDuration; + return this; + } - public IFrame setSpeed(float speed) { - this.speed = speed; - return this; - } + public boolean isCustomized() { + return customized; + } - public byte smoothType() { - return smooth; - } + public IFrame setCustomized(boolean customized) { + this.customized = customized; + return this; + } - public IFrame setSmooth(byte smooth) { - this.smooth = smooth; - return this; - } + public float getSpeed() { + return speed; + } - public IFrame useRenderTicks(boolean renderTicks) { - this.renderTicks = renderTicks; - return this; - } + public IFrame setSpeed(float speed) { + this.speed = speed; + return this; + } - public boolean useRenderTicks() { - return this.renderTicks; - } + public byte smoothType() { + return smooth; + } - public int getColorMarker() { - return this.colorMarker; - } + public IFrame setSmooth(byte smooth) { + this.smooth = smooth; + return this; + } - public void setColorMarker(int color) { - this.colorMarker = color; - } + public int getColorMarker() { + return this.colorMarker; + } - public void readFromNBT(NBTTagCompound compound){ - duration = compound.getInteger("Duration"); - if (compound.hasKey("ColorMarker")) { - this.setColorMarker(compound.getInteger("ColorMarker")); - } + public void setColorMarker(int color) { + this.colorMarker = color; + } - // Customized = TRUE if Speed or Smooth Exist - if(compound.hasKey("Speed")){ - customized = true; - speed = compound.getFloat("Speed"); - } - if(compound.hasKey("Smooth")){ - customized = true; - smooth = compound.getByte("Smooth"); - } - if(compound.hasKey("RenderTicks")){ - customized = true; - renderTicks = compound.getBoolean("RenderTicks"); - } + public String getComment() { + return this.comment; + } - if (!customized) { - this.speed = parent.speed; - this.smooth = parent.smooth; - this.renderTicks = parent.renderTicks; - } + public void setComment(String comment) { + this.comment = comment; + } - HashMap frameParts = new HashMap<>(); - NBTTagList list = compound.getTagList("FrameParts", 10); - for (int i = 0; i < list.tagCount(); i++) { - NBTTagCompound item = list.getCompoundTagAt(i); - FramePart framePart = new FramePart(); - framePart.readFromNBT(item); - if (!framePart.customized) { - framePart.smooth = this.smooth; - framePart.speed = this.speed; - } - frameParts.put(framePart.part,framePart); - } - this.frameParts = frameParts; - } + public void readFromNBT(NBTTagCompound compound){ + duration = compound.getInteger("Duration"); + if (compound.hasKey("ColorMarker")) { + this.setColorMarker(compound.getInteger("ColorMarker")); + } + if (compound.hasKey("Comment")) { + this.comment = compound.getString("Comment"); + } - public NBTTagCompound writeToNBT(){ - NBTTagCompound compound = new NBTTagCompound(); - compound.setInteger("Duration", duration); - compound.setInteger("ColorMarker", this.colorMarker); + // Customized = TRUE if Speed or Smooth Exist + if(compound.hasKey("Speed")){ + customized = true; + speed = compound.getFloat("Speed"); + } + if(compound.hasKey("Smooth")){ + customized = true; + smooth = compound.getByte("Smooth"); + } - if(customized){ - compound.setFloat("Speed", speed); - compound.setByte("Smooth", smooth); - compound.setBoolean("RenderTicks", renderTicks); - } + if (compound.hasKey("TickDuration")) { + customized = true; + this.tickDuration = compound.getInteger("TickDuration"); + } else if(compound.hasKey("RenderTicks")){ + customized = true; + this.tickDuration = compound.getBoolean("RenderTicks") ? 20 : 50; + } - NBTTagList list = new NBTTagList(); - for(FramePart framePart : frameParts.values()){ - NBTTagCompound item = framePart.writeToNBT(); - list.appendTag(item); - } - compound.setTag("FrameParts", list); - return compound; - } + if (!customized && parent != null) { + this.speed = parent.speed; + this.smooth = parent.smooth; + this.tickDuration = parent.tickDuration; + } - public Frame copy() { - Frame frame = new Frame(this.duration); - HashMap frameParts = this.frameParts; - for (Map.Entry entry : frameParts.entrySet()) { - frame.frameParts.put(entry.getKey(),entry.getValue().copy()); - } - frame.parent = this.parent; - frame.duration = this.duration; - frame.customized = this.customized; - frame.speed = this.speed; - frame.smooth = this.smooth; - frame.renderTicks = this.renderTicks; - frame.colorMarker = this.colorMarker; - return frame; - } + HashMap frameParts = new HashMap<>(); + NBTTagList list = compound.getTagList("FrameParts", 10); + for (int i = 0; i < list.tagCount(); i++) { + NBTTagCompound item = list.getCompoundTagAt(i); + FramePart framePart = new FramePart(); + framePart.readFromNBT(item); + if (!framePart.customized) { + framePart.smooth = this.smooth; + framePart.speed = this.speed; + } + frameParts.put(framePart.part,framePart); + } + this.frameParts = frameParts; + } + + public NBTTagCompound writeToNBT(){ + NBTTagCompound compound = new NBTTagCompound(); + compound.setInteger("Duration", duration); + compound.setInteger("ColorMarker", this.colorMarker); + compound.setString("Comment", this.comment); + + if(customized){ + compound.setFloat("Speed", speed); + compound.setByte("Smooth", smooth); + compound.setInteger("TickDuration", tickDuration); + } + + NBTTagList list = new NBTTagList(); + for(FramePart framePart : frameParts.values()){ + NBTTagCompound item = framePart.writeToNBT(); + list.appendTag(item); + } + compound.setTag("FrameParts", list); + return compound; + } + + public Frame copy() { + Frame frame = new Frame(this.duration); + HashMap frameParts = this.frameParts; + for (Map.Entry entry : frameParts.entrySet()) { + frame.frameParts.put(entry.getKey(),entry.getValue().copy()); + } + frame.parent = this.parent; + frame.duration = this.duration; + frame.customized = this.customized; + frame.speed = this.speed; + frame.smooth = this.smooth; + frame.tickDuration = this.tickDuration; + frame.colorMarker = this.colorMarker; + return frame; + } } diff --git a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java index 85096dfe0..041f81068 100644 --- a/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java +++ b/src/main/java/noppes/npcs/controllers/data/PlayerDataScript.java @@ -97,7 +97,7 @@ public class PlayerDataScript implements INpcScriptHandler { } public boolean isClient() { - return this.player.isClientWorld(); + return this.player != null && this.player.isClientWorld(); } public boolean getEnabled() { return ScriptController.Instance.playerScripts.enabled; diff --git a/src/main/java/noppes/npcs/util/MillisTimer.java b/src/main/java/noppes/npcs/util/MillisTimer.java new file mode 100644 index 000000000..82acb5c7f --- /dev/null +++ b/src/main/java/noppes/npcs/util/MillisTimer.java @@ -0,0 +1,84 @@ +package noppes.npcs.util; + +public class MillisTimer { + float ticksPerSecond; + private double lastHRTime; + public int elapsedTicks; + public float renderPartialTicks; + public float timerSpeed = 1.0F; + public float elapsedPartialTicks; + private long lastSyncSysClock; + private long lastSyncHRClock; + private long field_74285_i; + private double timeSyncAdjustment = 1.0D; + + public MillisTimer(float p_i1018_1_) + { + this.ticksPerSecond = p_i1018_1_; + this.lastSyncSysClock = this.getLastSyncSysClock(); + this.lastSyncHRClock = System.nanoTime() / 1000000L; + } + + /** + * Updates all fields of the Timer using the current time + */ + public void updateTimer() + { + long i = this.getLastSyncSysClock(); + long j = i - this.lastSyncSysClock; + long k = System.nanoTime() / 1000000L; + double d0 = (double)k / 1000.0D; + + if (j <= 1000L && j >= 0L) + { + this.field_74285_i += j; + + if (this.field_74285_i > 1000L) + { + long l = k - this.lastSyncHRClock; + double d1 = (double)this.field_74285_i / (double)l; + this.timeSyncAdjustment += (d1 - this.timeSyncAdjustment) * 0.20000000298023224D; + this.lastSyncHRClock = k; + this.field_74285_i = 0L; + } + + if (this.field_74285_i < 0L) + { + this.lastSyncHRClock = k; + } + } + else + { + this.lastHRTime = d0; + } + + this.lastSyncSysClock = i; + double d2 = (d0 - this.lastHRTime) * this.timeSyncAdjustment; + this.lastHRTime = d0; + + if (d2 < 0.0D) + { + d2 = 0.0D; + } + + if (d2 > 1.0D) + { + d2 = 1.0D; + } + + this.elapsedPartialTicks = (float)((double)this.elapsedPartialTicks + d2 * (double)this.timerSpeed * (double)this.ticksPerSecond); + this.elapsedTicks = (int)this.elapsedPartialTicks; + this.elapsedPartialTicks -= (float)this.elapsedTicks; + + if (this.elapsedTicks > 10) + { + this.elapsedTicks = 10; + } + + this.renderPartialTicks = this.elapsedPartialTicks; + } + + private long getLastSyncSysClock() { + return System.nanoTime() / 1_000_000L; + } +}