mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-19 14:59:25 +00:00
193 lines
8.7 KiB
Diff
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);
|
|
|