diff --git a/src/main/java/noppes/npcs/CommonProxy.java b/src/main/java/noppes/npcs/CommonProxy.java index 067e2f1b3..3f0270f9d 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,80 @@ 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.Animation; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.entity.EntityNPCInterface; +import noppes.npcs.util.MillisTimer; + +import java.util.HashSet; public class CommonProxy implements IGuiHandler { - - public boolean newVersionAvailable = false; - public int revision = 1; + public static HashSet clientPlayingAnimations = new HashSet<>(); + public static HashSet serverPlayingAnimations = new HashSet<>(); + protected MillisTimer animationTimer = new MillisTimer(1000); + protected long totalTicks; 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) { + if (!CustomNpcs.proxy.hasClient() || !Minecraft.getMinecraft().isGamePaused()) { + animationTimer.updateTimer(); + } + + HashSet playingAnimations = CustomNpcs.proxy.hasClient() ? clientPlayingAnimations : serverPlayingAnimations; + for (int i = 0; i < animationTimer.elapsedTicks; ++i) { + for (Animation animation : playingAnimations) { + if (animation.parent.isActive() && totalTicks % animation.currentFrame().tickDuration() == 0) { + animation.increaseTime(); + } + } + totalTicks++; + } + totalTicks %= 60 * 60 * 1000; + clientPlayingAnimations.removeIf(CommonProxy.this::removeAnimation); + serverPlayingAnimations.removeIf(CommonProxy.this::removeAnimation); + } + }}); + thread.setDaemon(true); + thread.start(); + } + + private boolean removeAnimation(Animation animation) { + if (animation.parent == null || animation.parent.animation != animation) return true; + + Entity entity = null; + if (animation.parent.parent instanceof DataDisplay) { + entity = ((DataDisplay)animation.parent.parent).npc; + } else { + if (animation.parent.parent instanceof PlayerData) { + entity = ((PlayerData) animation.parent.parent).player; + } else if (animation.parent.parent instanceof EntityPlayer) { + entity = (EntityPlayer) animation.parent.parent; + } + } + + if (entity == null) return true; + + if (CustomNpcs.proxy.hasClient()) { + return clientRemoveAnimation(entity); + } else { + return entity.worldObj == null || !entity.worldObj.loadedEntityList.contains(entity); + } + } + + @SideOnly(Side.CLIENT) + private boolean clientRemoveAnimation(Entity entity) { + return Minecraft.getMinecraft().currentScreen == null + && !Minecraft.getMinecraft().theWorld.loadedEntityList.contains(entity); + } + public PlayerData getPlayerData(EntityPlayer player) { return null; } @@ -166,4 +231,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/ClientCacheHandler.java b/src/main/java/noppes/npcs/client/ClientCacheHandler.java index 163cac820..bf9c920f4 100644 --- a/src/main/java/noppes/npcs/client/ClientCacheHandler.java +++ b/src/main/java/noppes/npcs/client/ClientCacheHandler.java @@ -1,6 +1,7 @@ package noppes.npcs.client; import net.minecraft.util.ResourceLocation; +import noppes.npcs.CommonProxy; import noppes.npcs.client.gui.OverlayQuestTracking; import noppes.npcs.client.gui.customoverlay.OverlayCustom; import noppes.npcs.client.renderer.ImageData; @@ -21,7 +22,6 @@ public class ClientCacheHandler { public static HashMap> skinOverlays = new HashMap<>(); public static HashMap playerAnimations = new HashMap<>(); - public static HashSet playingAnimations = new HashSet<>(); public static Party party; @@ -57,7 +57,7 @@ public class ClientCacheHandler { ClientCacheHandler.skinOverlays.clear(); ClientCacheHandler.playerAnimations.clear(); ClientCacheHandler.playerData.animationData.clearCache(); - ClientCacheHandler.playingAnimations.clear(); + CommonProxy.clientPlayingAnimations.clear(); } public static void clearSkinCache() { diff --git a/src/main/java/noppes/npcs/client/ClientProxy.java b/src/main/java/noppes/npcs/client/ClientProxy.java index 03fa6a542..d33558f3c 100644 --- a/src/main/java/noppes/npcs/client/ClientProxy.java +++ b/src/main/java/noppes/npcs/client/ClientProxy.java @@ -23,7 +23,6 @@ import net.minecraft.stats.Achievement; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ReportedException; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.Timer; import net.minecraft.world.World; import net.minecraftforge.client.MinecraftForgeClient; import net.minecraftforge.common.MinecraftForge; @@ -60,7 +59,6 @@ import noppes.npcs.config.ConfigMain; import noppes.npcs.config.StringCache; import noppes.npcs.constants.EnumGuiType; import noppes.npcs.containers.*; -import noppes.npcs.controllers.data.Animation; import noppes.npcs.controllers.data.PlayerData; import noppes.npcs.entity.*; import noppes.npcs.entity.data.ModelData; @@ -82,33 +80,8 @@ public class ClientProxy extends CommonProxy { public static FontContainer Font; - private static Timer animationTimer = new Timer(1000); - private static long totalTicks; - public void load() { - Thread thread = (new Thread("Animation Thread") { public void run() { - while (true) { - if (!Minecraft.getMinecraft().isGamePaused()) { - animationTimer.updateTimer(); - } - - try { - for (int i = 0; i < animationTimer.elapsedTicks; ++i) { - for (Animation animation : ClientCacheHandler.playingAnimations) { - if (animation.parent.isActive() && totalTicks % animation.currentFrame().tickDuration() == 0) { - animation.increaseTime(); - } - } - totalTicks++; - } - totalTicks %= 60 * 60 * 1000; - ClientCacheHandler.playingAnimations.removeIf(animation -> - animation.parent.animation != animation || !animation.parent.isActive()); - } catch (Exception ignored) {} - } - }}); - thread.setDaemon(true); - thread.start(); + this.createAnimationThread(); Font = new FontContainer(ConfigClient.FontType, ConfigClient.FontSize); createFolders(); diff --git a/src/main/java/noppes/npcs/controllers/data/Animation.java b/src/main/java/noppes/npcs/controllers/data/Animation.java index 9bf83f34d..6754a3825 100644 --- a/src/main/java/noppes/npcs/controllers/data/Animation.java +++ b/src/main/java/noppes/npcs/controllers/data/Animation.java @@ -220,7 +220,6 @@ public class Animation implements IAnimation { return compound; } - @SideOnly(Side.CLIENT) public void increaseTime() { if (paused) return; diff --git a/src/main/java/noppes/npcs/controllers/data/AnimationData.java b/src/main/java/noppes/npcs/controllers/data/AnimationData.java index 12dc2bbf0..3bfb538c5 100644 --- a/src/main/java/noppes/npcs/controllers/data/AnimationData.java +++ b/src/main/java/noppes/npcs/controllers/data/AnimationData.java @@ -9,6 +9,8 @@ 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.CustomNpcs; import noppes.npcs.DataDisplay; import noppes.npcs.Server; import noppes.npcs.api.handler.data.IAnimation; @@ -56,6 +58,10 @@ public class AnimationData implements IAnimationData { EntityLivingBase sendingEntity = parent instanceof PlayerData ? ((PlayerData) parent).player : parent instanceof DataDisplay ? ((DataDisplay) parent).npc : null; float range = parent instanceof PlayerData ? 160 : 60; if (sendingEntity != null) { + if (!CustomNpcs.proxy.hasClient()) { + CommonProxy.serverPlayingAnimations.add(this.animation); + } + 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)); @@ -153,18 +159,20 @@ public class AnimationData implements IAnimationData { } public void setAnimation(IAnimation animation) { - if (FMLCommonHandler.instance().getEffectiveSide() == Side.SERVER) { - this.animation = (Animation) animation; - } else { - this.clientSetAnimation(animation); + Animation newAnim = null; + if (animation != null) { + newAnim = new Animation(); + newAnim.readFromNBT(((Animation) animation).writeToNBT()); + newAnim.parent = this; } - } - @SideOnly(Side.CLIENT) - private void clientSetAnimation(IAnimation animation) { - Animation newAnim = new Animation(); - newAnim.readFromNBT(((Animation) animation).writeToNBT()); - if (this.isActive() && !newAnim.frames.isEmpty()) { + if (CustomNpcs.proxy.hasClient() && newAnim != null) { + CommonProxy.clientPlayingAnimations.remove(this.animation); + CommonProxy.clientPlayingAnimations.add(newAnim); + } + this.animation = newAnim; + + if (this.isActive() && newAnim != null && !newAnim.frames.isEmpty()) { Frame frame = (Frame) this.animation.currentFrame(); if (frame != null) { Frame firstFrame = newAnim.frames.get(0); @@ -180,9 +188,6 @@ public class AnimationData implements IAnimationData { } } } - this.animation = newAnim; - newAnim.parent = this; - ClientCacheHandler.playingAnimations.add(newAnim); } public IAnimation getAnimation() { 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..f149f548f --- /dev/null +++ b/src/main/java/noppes/npcs/util/MillisTimer.java @@ -0,0 +1,86 @@ +package noppes.npcs.util; + +import org.lwjgl.Sys; + +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 Sys.getTime() * 1000L / Sys.getTimerResolution(); + } +}