From 111ed5569b670439bafe24b44f4b3c077f00e726 Mon Sep 17 00:00:00 2001 From: Byteflux Date: Tue, 16 Jun 2015 05:55:15 -0700 Subject: [PATCH] Optimize explosions --- .../0056-Optimize-explosions.patch | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 Spigot-Server-Patches/0056-Optimize-explosions.patch diff --git a/Spigot-Server-Patches/0056-Optimize-explosions.patch b/Spigot-Server-Patches/0056-Optimize-explosions.patch new file mode 100644 index 000000000..ba30674c2 --- /dev/null +++ b/Spigot-Server-Patches/0056-Optimize-explosions.patch @@ -0,0 +1,153 @@ +From 506643b86c89a89100e35420d3511c9eb8b9d0a1 Mon Sep 17 00:00:00 2001 +From: Byteflux +Date: Tue, 16 Jun 2015 05:52:58 -0700 +Subject: [PATCH] Optimize explosions + +The process of determining an entity's exposure from explosions can be +expensive when there are hundreds or more entities in range. + +This patch adds a per-tick cache that is used for storing and retrieving +an entity's exposure during an explosion. + +diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java +index f40f465..4afb8d7 100644 +--- a/src/main/java/net/minecraft/server/Explosion.java ++++ b/src/main/java/net/minecraft/server/Explosion.java +@@ -129,7 +129,7 @@ public class Explosion { + d8 /= d11; + d9 /= d11; + d10 /= d11; +- double d12 = (double) this.world.a(vec3d, entity.getBoundingBox()); ++ double d12 = this.getBlockDensity(vec3d, entity.getBoundingBox()); // PaperSpigot - Optimize explosions + double d13 = (1.0D - d7) * d12; + + // entity.damageEntity(DamageSource.explosion(this), (float) ((int) ((d13 * d13 + d13) / 2.0D * 8.0D * (double) f3 + 1.0D)));+ // CraftBukkit start +@@ -294,4 +294,86 @@ public class Explosion { + public List getBlocks() { + return this.blocks; + } ++ ++ // PaperSpigot start - Optimize explosions ++ private float getBlockDensity(Vec3D vec3d, AxisAlignedBB aabb) { ++ if (!this.world.paperSpigotConfig.optimizeExplosions) { ++ return this.world.a(vec3d, aabb); ++ } ++ ++ CacheKey key = new CacheKey(this, aabb); ++ Float blockDensity = this.world.explosionDensityCache.get(key); ++ if (blockDensity == null) { ++ blockDensity = this.world.a(vec3d, aabb); ++ this.world.explosionDensityCache.put(key, blockDensity); ++ } ++ ++ return blockDensity; ++ } ++ ++ static class CacheKey { ++ private final World world; ++ private final double posX, posY, posZ; ++ private final double minX, minY, minZ; ++ private final double maxX, maxY, maxZ; ++ ++ public CacheKey(Explosion explosion, AxisAlignedBB aabb) { ++ this.world = explosion.world; ++ this.posX = explosion.posX; ++ this.posY = explosion.posY; ++ this.posZ = explosion.posZ; ++ this.minX = aabb.a; ++ this.minY = aabb.b; ++ this.minZ = aabb.c; ++ this.maxX = aabb.d; ++ this.maxY = aabb.e; ++ this.maxZ = aabb.f; ++ } ++ ++ @Override ++ public boolean equals(Object o) { ++ if (this == o) return true; ++ if (o == null || getClass() != o.getClass()) return false; ++ ++ CacheKey cacheKey = (CacheKey) o; ++ ++ if (Double.compare(cacheKey.posX, posX) != 0) return false; ++ if (Double.compare(cacheKey.posY, posY) != 0) return false; ++ if (Double.compare(cacheKey.posZ, posZ) != 0) return false; ++ if (Double.compare(cacheKey.minX, minX) != 0) return false; ++ if (Double.compare(cacheKey.minY, minY) != 0) return false; ++ if (Double.compare(cacheKey.minZ, minZ) != 0) return false; ++ if (Double.compare(cacheKey.maxX, maxX) != 0) return false; ++ if (Double.compare(cacheKey.maxY, maxY) != 0) return false; ++ if (Double.compare(cacheKey.maxZ, maxZ) != 0) return false; ++ return world.equals(cacheKey.world); ++ } ++ ++ @Override ++ public int hashCode() { ++ int result; ++ long temp; ++ result = world.hashCode(); ++ temp = Double.doubleToLongBits(posX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(posY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(posZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(minZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxX); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxY); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ temp = Double.doubleToLongBits(maxZ); ++ result = 31 * result + (int) (temp ^ (temp >>> 32)); ++ return result; ++ } ++ } ++ // PaperSpigot end + } +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 77fe950..a3fb54b 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -859,6 +859,7 @@ public abstract class MinecraftServer implements Runnable, ICommandListener, IAs + worldserver.timings.tracker.stopTiming(); // Spigot + this.methodProfiler.b(); + this.methodProfiler.b(); ++ worldserver.explosionDensityCache.clear(); // PaperSpigot - Optimize explosions + // } // CraftBukkit + + // this.i[i][this.ticks % 100] = System.nanoTime() - j; // CraftBukkit +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 480a6d8..26091b1 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -132,6 +132,7 @@ public abstract class World implements IBlockAccess { + public static boolean haveWeSilencedAPhysicsCrash; + public static String blockLocation; + private int tileTickPosition; ++ public final Map explosionDensityCache = new HashMap(); // PaperSpigot - Optimize explosions + + public static long chunkToKey(int x, int z) + { +diff --git a/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java b/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java +index 3f42ca9..9d8791f 100644 +--- a/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java ++++ b/src/main/java/org/github/paperspigot/PaperSpigotWorldConfig.java +@@ -344,4 +344,10 @@ public class PaperSpigotWorldConfig + { + fallingBlocksCollideWithSigns = getBoolean( "falling-blocks-collide-with-signs", false ); + } ++ ++ public boolean optimizeExplosions; ++ private void optimizeExplosions() ++ { ++ optimizeExplosions = getBoolean( "optimize-explosions", false ); ++ } + } +-- +1.9.5.msysgit.1 +