9
0
mirror of https://github.com/BX-Team/DivineMC.git synced 2025-12-19 14:59:25 +00:00
Files
DivineMC/divinemc-server/minecraft-patches/features/0014-Optimize-explosions.patch

193 lines
8.7 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
Date: Sat, 1 Feb 2025 16:57:01 +0300
Subject: [PATCH] Optimize explosions
diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java
index 6bddf42504039f2be5eb9a5a35a0835e0e3239fe..ea6da35e6c38a0b8b67d0b7a1426445eadfb540c 100644
--- a/net/minecraft/world/level/ServerExplosion.java
+++ b/net/minecraft/world/level/ServerExplosion.java
@@ -375,6 +375,11 @@ public class ServerExplosion implements Explosion {
}
private List<BlockPos> calculateExplodedPositions() {
+ // DivineMC start - Optimize explosions
+ if (org.bxteam.divinemc.DivineConfig.enableFasterTntOptimization && !level.isClientSide && !(getIndirectSourceEntity() instanceof net.minecraft.world.entity.monster.breeze.Breeze)) {
+ return doExplosionA(this);
+ }
+ // DivineMC end - Optimize explosions
// Paper start - collision optimisations
final ObjectArrayList<BlockPos> ret = new ObjectArrayList<>();
@@ -473,6 +478,157 @@ public class ServerExplosion implements Explosion {
// Paper end - collision optimisations
}
+ // DivineMC start - Optimize explosions
+ private static final it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap<org.apache.commons.lang3.tuple.Pair<net.minecraft.world.phys.Vec3, net.minecraft.world.phys.AABB>> densityCache = new it.unimi.dsi.fastutil.objects.Object2DoubleOpenHashMap<>();
+ private static final it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<net.minecraft.core.BlockPos, net.minecraft.world.level.block.state.BlockState> stateCache = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>();
+ private static final it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<net.minecraft.core.BlockPos, net.minecraft.world.level.material.FluidState> fluidCache = new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>();
+ private static final BlockPos.MutableBlockPos posMutable = new BlockPos.MutableBlockPos(0, 0, 0);
+ private static final it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<net.minecraft.core.BlockPos> affectedBlockPositionsSet = new it.unimi.dsi.fastutil.objects.ObjectOpenHashSet<>();
+ private static boolean firstRay;
+ private static boolean rayCalcDone;
+
+ public static @org.jetbrains.annotations.NotNull List<BlockPos> doExplosionA(ServerExplosion e) {
+ List<BlockPos> toBlow;
+
+ if (!org.bxteam.divinemc.DivineConfig.explosionNoBlockDamage && e.damageSource != null) {
+ rayCalcDone = false;
+ firstRay = true;
+ getAffectedPositionsOnPlaneY(e, 0, 0, 15, 0, 15); // bottom
+ getAffectedPositionsOnPlaneY(e, 15, 0, 15, 0, 15); // top
+ getAffectedPositionsOnPlaneX(e, 0, 1, 14, 0, 15); // west
+ getAffectedPositionsOnPlaneX(e, 15, 1, 14, 0, 15); // east
+ getAffectedPositionsOnPlaneZ(e, 0, 1, 14, 1, 14); // north
+ getAffectedPositionsOnPlaneZ(e, 15, 1, 14, 1, 14); // south
+ stateCache.clear();
+ fluidCache.clear();
+
+ toBlow = new ArrayList<>(affectedBlockPositionsSet);
+ affectedBlockPositionsSet.clear();
+ } else {
+ toBlow = java.util.Collections.emptyList();
+ }
+ densityCache.clear();
+
+ return toBlow;
+ }
+
+ private static void getAffectedPositionsOnPlaneX(Explosion e, int x, int yStart, int yEnd, int zStart, int zEnd) {
+ if (!rayCalcDone) {
+ final double xRel = (double) x / 15.0D * 2.0D - 1.0D;
+
+ for (int z = zStart; z <= zEnd; ++z) {
+ double zRel = (double) z / 15.0D * 2.0D - 1.0D;
+
+ for (int y = yStart; y <= yEnd; ++y) {
+ double yRel = (double) y / 15.0D * 2.0D - 1.0D;
+
+ if (checkAffectedPosition((ServerExplosion) e, xRel, yRel, zRel)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private static void getAffectedPositionsOnPlaneY(Explosion e, int y, int xStart, int xEnd, int zStart, int zEnd) {
+ if (!rayCalcDone) {
+ final double yRel = (double) y / 15.0D * 2.0D - 1.0D;
+
+ for (int z = zStart; z <= zEnd; ++z) {
+ double zRel = (double) z / 15.0D * 2.0D - 1.0D;
+
+ for (int x = xStart; x <= xEnd; ++x) {
+ double xRel = (double) x / 15.0D * 2.0D - 1.0D;
+
+ if (checkAffectedPosition((ServerExplosion) e, xRel, yRel, zRel)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private static void getAffectedPositionsOnPlaneZ(Explosion e, int z, int xStart, int xEnd, int yStart, int yEnd) {
+ if (!rayCalcDone) {
+ final double zRel = (double) z / 15.0D * 2.0D - 1.0D;
+
+ for (int x = xStart; x <= xEnd; ++x) {
+ double xRel = (double) x / 15.0D * 2.0D - 1.0D;
+
+ for (int y = yStart; y <= yEnd; ++y) {
+ double yRel = (double) y / 15.0D * 2.0D - 1.0D;
+
+ if (checkAffectedPosition((ServerExplosion) e, xRel, yRel, zRel)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean checkAffectedPosition(ServerExplosion e, double xRel, double yRel, double zRel) {
+ double len = Math.sqrt(xRel * xRel + yRel * yRel + zRel * zRel);
+ double xInc = (xRel / len) * 0.3;
+ double yInc = (yRel / len) * 0.3;
+ double zInc = (zRel / len) * 0.3;
+ float rand = e.level().random.nextFloat();
+ float sizeRand = (org.bxteam.divinemc.DivineConfig.tntRandomRange >= 0 ? (float) org.bxteam.divinemc.DivineConfig.tntRandomRange : rand);
+ float size = e.radius() * (0.7F + sizeRand * 0.6F);
+ Vec3 vec3 = e.center();
+ double posX = vec3.x;
+ double posY = vec3.y;
+ double posZ = vec3.z;
+
+ for (float f1 = 0.3F; size > 0.0F; size -= 0.22500001F) {
+ posMutable.set(posX, posY, posZ);
+
+ // Don't query already cached positions again from the world
+ BlockState state = stateCache.get(posMutable);
+ FluidState fluid = fluidCache.get(posMutable);
+ BlockPos posImmutable = null;
+
+ if (state == null) {
+ posImmutable = posMutable.immutable();
+ state = e.level().getBlockState(posImmutable);
+ stateCache.put(posImmutable, state);
+ fluid = e.level().getFluidState(posImmutable);
+ fluidCache.put(posImmutable, fluid);
+ }
+
+ if (!state.isAir()) {
+ float resistance = Math.max(state.getBlock().getExplosionResistance(), fluid.getExplosionResistance());
+
+ if (e.source != null) {
+ resistance = e.source.getBlockExplosionResistance(e, e.level(), posMutable, state, fluid, resistance);
+ }
+
+ size -= (resistance + 0.3F) * 0.3F;
+ }
+
+ if (size > 0.0F) {
+ if ((e.source == null || e.source.shouldBlockExplode(e, e.level(), posMutable, state, size)))
+ affectedBlockPositionsSet.add(posImmutable != null ? posImmutable : posMutable.immutable());
+ } else if (firstRay) {
+ rayCalcDone = true;
+ return true;
+ }
+
+ firstRay = false;
+
+ posX += xInc;
+ posY += yInc;
+ posZ += zInc;
+ }
+
+ return false;
+ }
+
+ private Optional<Float> noBlockCalcsWithNoBLockDamage(final ExplosionDamageCalculator instance, final Explosion explosion, final BlockGetter blockGetter, final BlockPos blockPos, final BlockState blockState, final FluidState fluidState) {
+ if (org.bxteam.divinemc.DivineConfig.explosionNoBlockDamage) return Optional.of(Blocks.BEDROCK.getExplosionResistance());
+ return instance.getBlockExplosionResistance(explosion, blockGetter, blockPos, blockState, fluidState);
+ }
+ // DivineMC end - Optimize explosions
+
private void hurtEntities() {
float f = this.radius * 2.0F;
int floor = Mth.floor(this.center.x - f - 1.0);
@@ -565,6 +721,11 @@ public class ServerExplosion implements Explosion {
}
private void interactWithBlocks(List<BlockPos> blocks) {
+ // DivineMC start - Optimize explosions
+ if (org.bxteam.divinemc.DivineConfig.explosionNoBlockDamage) {
+ blocks.clear();
+ }
+ // DivineMC end - Optimize explosions
List<ServerExplosion.StackCollector> list = new ArrayList<>();
Util.shuffle(blocks, this.level.random);