From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Samsuik Date: Mon, 22 Apr 2024 23:01:26 +0100 Subject: [PATCH] Replace explosion density cache diff --git a/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java b/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java new file mode 100644 index 0000000000000000000000000000000000000000..b760b03f9ddc1fb2aed135105030fc1b5dc2c9c9 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java @@ -0,0 +1,65 @@ +package me.samsuik.sakura.explosion.density; + +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; + +/** + * This is a replacement for papers explosion density cache to be more lenient and efficient. + */ +public final class BlockDensityCache { + public static final float UNKNOWN_DENSITY = -1.0f; + + private final Int2ObjectOpenHashMap densityDataMap = new Int2ObjectOpenHashMap<>(); + private DensityData data; + private int key; + private boolean knownSource; + + public float getDensity(Vec3 explosion, Entity entity) { + int key = getKey(explosion, entity); + DensityData data = this.densityDataMap.get(key); + + if (data != null && data.hasPosition(explosion, entity.getBoundingBox())) { + return data.density(); + } else { + this.knownSource = data != null && data.complete() && data.isExplosionPosition(explosion); + this.data = data; + this.key = key; + return UNKNOWN_DENSITY; + } + } + + public float getKnownDensity(Vec3 point) { + if (this.knownSource && this.data.isKnownPosition(point)) { + return this.data.density(); + } else { + return UNKNOWN_DENSITY; + } + } + + public void putDensity(Vec3 explosion, Entity entity, float density) { + if (this.data == null || !this.data.complete()) { + this.densityDataMap.put(this.key, new DensityData(explosion, entity, density)); + } else if (this.data.density() == density) { + this.data.expand(explosion, entity); + } + } + + public void clear(long tick) { + // trim size every 30 seconds + if (tick != -1 && tick % 600 == 0) + this.densityDataMap.trim(); + this.densityDataMap.clear(); + } + + private static int getKey(Vec3 explosion, Entity entity) { + int key = Mth.floor(explosion.x()); + key = 31 * key + Mth.floor(explosion.y()); + key = 31 * key + Mth.floor(explosion.z()); + key = 31 * key + entity.getBlockX(); + key = 31 * key + entity.getBlockY(); + key = 31 * key + entity.getBlockZ(); + return key; + } +} diff --git a/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java b/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java new file mode 100644 index 0000000000000000000000000000000000000000..d7e24638f07f243502004970ab4ce646cbe1e436 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java @@ -0,0 +1,47 @@ +package me.samsuik.sakura.explosion.density; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; + +public final class DensityData { + private AABB source; + private AABB known; + private AABB entity; + private final float density; + private final boolean complete; + + public DensityData(Vec3 explosion, Entity entity, float density) { + this.source = new AABB(explosion, explosion); + this.known = new AABB(entity.position(), entity.position()); + this.entity = entity.getBoundingBox(); + this.density = density; + this.complete = Math.abs(density - 0.5f) == 0.5f; + } + + public float density() { + return this.density; + } + + public boolean complete() { + return this.complete; + } + + public boolean hasPosition(Vec3 explosion, AABB entity) { + return this.isExplosionPosition(explosion) && this.entity.isAABBInBounds(entity); + } + + public boolean isKnownPosition(Vec3 point) { + return this.entity.isVec3InBounds(point); + } + + public boolean isExplosionPosition(Vec3 explosion) { + return this.source.isVec3InBounds(explosion); + } + + public void expand(Vec3 explosion, Entity entity) { + this.source = this.source.expand(explosion); + this.known = this.known.expand(entity.position()); + this.entity = this.entity.minmax(entity.getBoundingBox()); + } +} diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java index 1358f800a29ef15163442331100816bb418ae3f6..f14abf532e9cd80e0a270826143c7489a4f4a5e4 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1568,6 +1568,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop resourcekey, Holder holder, Supplier supplier, boolean flag, boolean flag1, long i, int j, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider, org.bukkit.World.Environment env, java.util.function.Function paperWorldConfigCreator, Supplier sakuraWorldConfigCreator, java.util.concurrent.Executor executor) { // Sakura // Paper - Async-Anti-Xray - Pass executor this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) worlddatamutable).getLevelName()); // Spigot diff --git a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java index 6923a34e82e49004b29a77e57fea8c2a00180299..56dce65e4d5070f7b08b07c4412ef95a54f3e1c7 100644 --- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java @@ -99,6 +99,11 @@ public abstract class BasePressurePlateBlock extends Block { if (output != j) { BlockState iblockdata1 = this.setSignalForState(state, j); + // Sakura start - explosion density cache + if (!world.paperConfig().environment.optimizeExplosions) { + world.densityCache.clear(-1); + } + // Sakura end - explosion density cache world.setBlock(pos, iblockdata1, 2); this.updateNeighbours(world, pos); world.setBlocksDirty(pos, state, iblockdata1); diff --git a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java index 004dce26ff073f1de52a84cd425c4f60fdab5e50..89928300608865a2cea6834fa0ac98a0796140e0 100644 --- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java @@ -164,6 +164,11 @@ public class TripWireHookBlock extends Block { blockposition1 = pos.relative(enumdirection, j); Direction enumdirection1 = enumdirection.getOpposite(); + // Sakura start - explosion density cache + if (!world.paperConfig().environment.optimizeExplosions) { + world.densityCache.clear(-1); + } + // Sakura end - explosion density cache world.setBlock(blockposition1, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection1), 3); this.notifyNeighbors(world, blockposition1, enumdirection1); this.emitState(world, blockposition1, flag4, flag5, flag2, flag3); diff --git a/src/main/java/net/minecraft/world/phys/AABB.java b/src/main/java/net/minecraft/world/phys/AABB.java index 68cc6f2a78a06293a29317fda72ab3ee79b3533a..a142bf12ef0b8c8d41cab846da2e161700f2db2b 100644 --- a/src/main/java/net/minecraft/world/phys/AABB.java +++ b/src/main/java/net/minecraft/world/phys/AABB.java @@ -367,4 +367,28 @@ public class AABB { public static AABB ofSize(Vec3 center, double dx, double dy, double dz) { return new AABB(center.x - dx / 2.0D, center.y - dy / 2.0D, center.z - dz / 2.0D, center.x + dx / 2.0D, center.y + dy / 2.0D, center.z + dz / 2.0D); } + + // Sakura start - explosion density cache + public final boolean isAABBInBounds(AABB bb) { + return this.minX <= bb.minX && this.maxX >= bb.maxX + && this.minY <= bb.minY && this.maxY >= bb.maxY + && this.minZ <= bb.minZ && this.maxZ >= bb.maxZ; + } + + public final boolean isVec3InBounds(Vec3 p) { + return this.minX <= p.x && this.maxX >= p.x + && this.minY <= p.y && this.maxY >= p.y + && this.minZ <= p.z && this.maxZ >= p.z; + } + + public final AABB expand(Vec3 pos) { + double minX = Math.min(this.minX, pos.x); + double minY = Math.min(this.minY, pos.y); + double minZ = Math.min(this.minZ, pos.z); + double maxX = Math.max(this.maxX, pos.x); + double maxY = Math.max(this.maxY, pos.y); + double maxZ = Math.max(this.maxZ, pos.z); + return new AABB(minX, minY, minZ, maxX, maxY, maxZ); + } + // Sakura end - explosion density cache }