2021-06-11 14:02:28 +02:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Byteflux <byte@byteflux.net>
|
|
|
|
Date: Wed, 2 Mar 2016 11:59:48 -0600
|
|
|
|
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/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
2023-12-05 23:25:12 +01:00
|
|
|
index 2f04f10f5819be04b98ac0b52a2d7f4dfa525cea..e0a2759169f41b68b8e1bc48f0b323c0a4bc1fed 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
2023-12-05 20:39:26 +01:00
|
|
|
@@ -1492,6 +1492,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
|
2021-06-11 14:02:28 +02:00
|
|
|
|
|
|
|
this.profiler.pop();
|
|
|
|
this.profiler.pop();
|
|
|
|
+ worldserver.explosionDensityCache.clear(); // Paper - Optimize explosions
|
|
|
|
}
|
|
|
|
|
|
|
|
this.profiler.popPush("connection");
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
|
2023-12-05 20:39:26 +01:00
|
|
|
index c5d644876e0c92a444a574ee7571227e19b28482..4e382cfae7a3a1889bc36bad24c6ea38b7eb14a6 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/Explosion.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
|
2023-12-05 20:39:26 +01:00
|
|
|
@@ -279,7 +279,7 @@ public class Explosion {
|
|
|
|
// CraftBukkit end
|
|
|
|
}
|
2021-06-11 14:02:28 +02:00
|
|
|
|
2023-12-05 20:39:26 +01:00
|
|
|
- double d12 = (1.0D - d7) * (double) Explosion.getSeenPercent(vec3d, entity);
|
|
|
|
+ double d12 = (1.0D - d7) * this.getBlockDensity(vec3d, entity); // Paper - Optimize explosions
|
|
|
|
double d13;
|
|
|
|
|
|
|
|
if (entity instanceof LivingEntity) {
|
|
|
|
@@ -520,4 +520,84 @@ public class Explosion {
|
2021-06-11 14:02:28 +02:00
|
|
|
|
|
|
|
private BlockInteraction() {}
|
|
|
|
}
|
|
|
|
+ // Paper start - Optimize explosions
|
|
|
|
+ private float getBlockDensity(Vec3 vec3d, Entity entity) {
|
2022-06-09 10:51:45 +02:00
|
|
|
+ if (!this.level.paperConfig().environment.optimizeExplosions) {
|
2021-06-11 14:02:28 +02:00
|
|
|
+ return getSeenPercent(vec3d, entity);
|
|
|
|
+ }
|
|
|
|
+ CacheKey key = new CacheKey(this, entity.getBoundingBox());
|
|
|
|
+ Float blockDensity = this.level.explosionDensityCache.get(key);
|
|
|
|
+ if (blockDensity == null) {
|
|
|
|
+ blockDensity = getSeenPercent(vec3d, entity);
|
|
|
|
+ this.level.explosionDensityCache.put(key, blockDensity);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return blockDensity;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ static class CacheKey {
|
|
|
|
+ private final Level world;
|
|
|
|
+ private final double posX, posY, posZ;
|
|
|
|
+ private final double minX, minY, minZ;
|
|
|
|
+ private final double maxX, maxY, maxZ;
|
|
|
|
+
|
|
|
|
+ public CacheKey(Explosion explosion, AABB aabb) {
|
|
|
|
+ this.world = explosion.level;
|
|
|
|
+ this.posX = explosion.x;
|
|
|
|
+ this.posY = explosion.y;
|
|
|
|
+ this.posZ = explosion.z;
|
|
|
|
+ this.minX = aabb.minX;
|
|
|
|
+ this.minY = aabb.minY;
|
|
|
|
+ this.minZ = aabb.minZ;
|
|
|
|
+ this.maxX = aabb.maxX;
|
|
|
|
+ this.maxY = aabb.maxY;
|
|
|
|
+ this.maxZ = aabb.maxZ;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // Paper end
|
|
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
2023-12-05 20:39:26 +01:00
|
|
|
index 8bfab45b506aa514956a99354a7dc5009ffa9cbf..cf081c6d270053b7d9a042b65495fe17f0ee4826 100644
|
2021-06-11 14:02:28 +02:00
|
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
2023-12-05 20:39:26 +01:00
|
|
|
@@ -170,6 +170,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
2021-06-11 14:02:28 +02:00
|
|
|
private org.spigotmc.TickLimiter entityLimiter;
|
|
|
|
private org.spigotmc.TickLimiter tileLimiter;
|
|
|
|
private int tileTickPosition;
|
|
|
|
+ public final Map<Explosion.CacheKey, Float> explosionDensityCache = new HashMap<>(); // Paper - Optimize explosions
|
|
|
|
|
|
|
|
public CraftWorld getWorld() {
|
|
|
|
return this.world;
|