From 37f24ae882a589b240932e8200b1baf7522c96f1 Mon Sep 17 00:00:00 2001 From: Unknown Date: Sun, 14 Apr 2019 22:02:22 +0200 Subject: [PATCH] Improved fall damage handler - allows entities with same id in different worlds - reduce memory footprint over time --- .../java/cr0s/warpdrive/LocalProfiler.java | 22 ++++++---- .../cr0s/warpdrive/event/LivingHandler.java | 42 +++++++++++++++---- .../cr0s/warpdrive/event/WorldHandler.java | 1 + 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/main/java/cr0s/warpdrive/LocalProfiler.java b/src/main/java/cr0s/warpdrive/LocalProfiler.java index eab39b04..4c0d0910 100644 --- a/src/main/java/cr0s/warpdrive/LocalProfiler.java +++ b/src/main/java/cr0s/warpdrive/LocalProfiler.java @@ -83,6 +83,10 @@ public class LocalProfiler { } public static void stop() { + stop(0L); + } + + public static void stop(final long tolerance_us) { if (stack.isEmpty()) { return; } @@ -90,7 +94,7 @@ public class LocalProfiler { final StackElement stackElement = stack.pop(); final long end = System.nanoTime(); final long timeElapsed = end - stackElement.start; - + if (!stack.isEmpty()) { final StackElement nextStackElement = stack.peek(); nextStackElement.internal += timeElapsed; @@ -99,12 +103,16 @@ public class LocalProfiler { // convert to microseconds final long self = (timeElapsed - stackElement.internal) / 1000; final long total = timeElapsed / 1000; - if (total == self) { - WarpDrive.logger.info(String.format("Profiling %s: %.3f ms", - stackElement.name, (self / 1000.0F) )); - } else { - WarpDrive.logger.info(String.format("Profiling %s: %.3f ms, total; %.3f ms", - stackElement.name, (self / 1000.0F), total / 1000.0F )); + + // only log if it was too slow + if (self > tolerance_us) { + if (total == self) { + WarpDrive.logger.info(String.format("Profiling %s: %.3f ms", + stackElement.name, (self / 1000.0F) )); + } else { + WarpDrive.logger.info(String.format("Profiling %s: %.3f ms, total; %.3f ms", + stackElement.name, (self / 1000.0F), total / 1000.0F )); + } } } } diff --git a/src/main/java/cr0s/warpdrive/event/LivingHandler.java b/src/main/java/cr0s/warpdrive/event/LivingHandler.java index 9c681af0..b82f3d9a 100644 --- a/src/main/java/cr0s/warpdrive/event/LivingHandler.java +++ b/src/main/java/cr0s/warpdrive/event/LivingHandler.java @@ -2,6 +2,7 @@ package cr0s.warpdrive.event; import cr0s.warpdrive.BreathingManager; import cr0s.warpdrive.Commons; +import cr0s.warpdrive.LocalProfiler; import cr0s.warpdrive.WarpDrive; import cr0s.warpdrive.block.forcefield.BlockForceField; import cr0s.warpdrive.data.CelestialObjectManager; @@ -13,9 +14,11 @@ import cr0s.warpdrive.data.Vector3; import cr0s.warpdrive.data.VectorI; import java.util.HashMap; +import java.util.Iterator; import java.util.UUID; import net.minecraft.block.Block; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; @@ -28,6 +31,7 @@ import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraft.world.WorldServer; +import net.minecraftforge.common.DimensionManager; import net.minecraftforge.event.entity.living.EnderTeleportEvent; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.event.entity.living.LivingFallEvent; @@ -35,8 +39,8 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class LivingHandler { - private final HashMap player_cloakTicks; - private final HashMap entity_yMotion; + private static final HashMap player_cloakTicks = new HashMap<>(); + private static final HashMap entity_yMotion = new HashMap<>(); private static final int CLOAK_CHECK_TIMEOUT_TICKS = 100; @@ -45,9 +49,32 @@ public class LivingHandler { private static final int BORDER_BYPASS_PULL_BACK_BLOCKS = 16; private static final int BORDER_BYPASS_DAMAGES_PER_TICK = 9000; - public LivingHandler() { - player_cloakTicks = new HashMap<>(); - entity_yMotion = new HashMap<>(); + private static final int PURGE_PERIOD_TICKS = 6000; // 5 mn + + private static int tickUpdate = PURGE_PERIOD_TICKS; + + public static void updateTick() { + tickUpdate--; + if (tickUpdate < 0) { + tickUpdate = PURGE_PERIOD_TICKS; + LocalProfiler.start("LivingHandler cleanup"); + final Iterator iterator = entity_yMotion.keySet().iterator(); + while (iterator.hasNext()) { + final Long key = iterator.next(); + final int dimensionId = (int) (key >> 32); + final WorldServer worldServer = DimensionManager.getWorld(dimensionId); + if (worldServer == null) { + iterator.remove(); + continue; + } + final Entity entity = worldServer.getEntityByID((int) (key & 0xFFFFFFFFL)); + if (entity == null) { + iterator.remove(); + // continue; + } + } + LocalProfiler.stop(1000); + } } @SubscribeEvent @@ -62,8 +89,9 @@ public class LivingHandler { final int z = MathHelper.floor(entityLivingBase.posZ); // *** save motion for fall damage computation + // note: dead entities don't tick. Checking health level is too taxing. Hence, cleanup is done indirectly. if (!entityLivingBase.onGround) { - entity_yMotion.put(entityLivingBase.getEntityId(), entityLivingBase.motionY); + entity_yMotion.put((long) entityLivingBase.dimension << 32 | entityLivingBase.getEntityId(), entityLivingBase.motionY); } // *** world border handling @@ -228,7 +256,7 @@ public class LivingHandler { // cancel in case of very low speed final EntityLivingBase entityLivingBase = event.getEntityLiving(); - Double motionY = entity_yMotion.get(entityLivingBase.getEntityId()); + Double motionY = entity_yMotion.get((long) entityLivingBase.dimension << 32 | entityLivingBase.getEntityId()); if (motionY == null) { motionY = entityLivingBase.motionY; } diff --git a/src/main/java/cr0s/warpdrive/event/WorldHandler.java b/src/main/java/cr0s/warpdrive/event/WorldHandler.java index eb9955ba..34772660 100644 --- a/src/main/java/cr0s/warpdrive/event/WorldHandler.java +++ b/src/main/java/cr0s/warpdrive/event/WorldHandler.java @@ -119,6 +119,7 @@ public class WorldHandler { } AbstractSequencer.updateTick(); + LivingHandler.updateTick(); } @SubscribeEvent