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..35454e122e87892099226ba8fd8d444664be9037 --- /dev/null +++ b/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java @@ -0,0 +1,62 @@ +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 invalidate() { + 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 012bec9a32acc26f65c8efbfde341b0d15a4e822..8041737aa751bec1c51ee3d9dacd6dfb2b845265 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -1823,6 +1823,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop resourcekey, RegistryAccess iregistrycustom, 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 - sakura configuration files// Paper - create paper world config & Anti-Xray 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 1aa36b456b1c635d3184aeab70d1d84266e22c4b..afb76b13f404a12a5f5b9ffe72756d31290a9a85 100644 --- a/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java +++ b/src/main/java/net/minecraft/world/level/block/BasePressurePlateBlock.java @@ -109,6 +109,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.invalidate(); + } + // 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 76aca266d3f3222502ff4c196228f08fcd88c5f8..b965d1b38a0a3f08531060039e46913dff3bfd0e 100644 --- a/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java +++ b/src/main/java/net/minecraft/world/level/block/TripWireHookBlock.java @@ -173,6 +173,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.invalidate(); + } + // Sakura end - explosion density cache world.setBlock(blockposition1, (BlockState) iblockdata3.setValue(TripWireHookBlock.FACING, enumdirection1), 3); TripWireHookBlock.notifyNeighbors(block, world, blockposition1, enumdirection1); TripWireHookBlock.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 29123f3a2f211c08d1a9ccf62ca9bc9822f90111..a63bd7945eef572615b1aa4a4914fa385b25cad2 100644 --- a/src/main/java/net/minecraft/world/phys/AABB.java +++ b/src/main/java/net/minecraft/world/phys/AABB.java @@ -508,4 +508,28 @@ public class AABB { public static AABB ofSize(Vec3 center, double dx, double dy, double dz) { return new AABB(center.x - dx / 2.0, center.y - dy / 2.0, center.z - dz / 2.0, center.x + dx / 2.0, center.y + dy / 2.0, center.z + dz / 2.0); } + + // 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 }