mirror of
https://github.com/Samsuik/Sakura.git
synced 2025-12-24 01:09:16 +00:00
Clean up and fix numerous issues with optimise explosions
This commit is contained in:
@@ -142,12 +142,13 @@ index 0000000000000000000000000000000000000000..3f6f34cc617efaad420485a7f613cfca
|
||||
+}
|
||||
diff --git a/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java b/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4f9880d35347dd008aa2ee6e67f35301ff37a4c0
|
||||
index 0000000000000000000000000000000000000000..8a8b4169c8928459f6b51150bd8e67d0a309ca08
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java
|
||||
@@ -0,0 +1,391 @@
|
||||
@@ -0,0 +1,403 @@
|
||||
+package me.samsuik.sakura.explosion;
|
||||
+
|
||||
+import me.samsuik.sakura.entity.EntityState;
|
||||
+import net.minecraft.core.BlockPos;
|
||||
+import net.minecraft.core.particles.ParticleOptions;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
@@ -155,6 +156,7 @@ index 0000000000000000000000000000000000000000..4f9880d35347dd008aa2ee6e67f35301
|
||||
+import net.minecraft.util.Mth;
|
||||
+import net.minecraft.world.damagesource.DamageSource;
|
||||
+import net.minecraft.world.entity.Entity;
|
||||
+import net.minecraft.world.entity.EntityType;
|
||||
+import net.minecraft.world.entity.LivingEntity;
|
||||
+import net.minecraft.world.entity.boss.EnderDragonPart;
|
||||
+import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
|
||||
@@ -201,40 +203,39 @@ index 0000000000000000000000000000000000000000..4f9880d35347dd008aa2ee6e67f35301
|
||||
+ @Override
|
||||
+ public void explode() {
|
||||
+ if (this.radius < 0.1F) {
|
||||
+ for (int i = 1; i < source.getStacked() && !wasCanceled; ++i) {
|
||||
+ this.finalizeExplosion(false);
|
||||
+ for (int i = 1; i < source.getStacked(); ++i) {
|
||||
+ getToBlow().clear();
|
||||
+ ((ServerLevel) level).notifyPlayersOfExplosion(x, y, z, radius, this);
|
||||
+ finalizeExplosion(false);
|
||||
+ }
|
||||
+
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ PrimedTnt origin = (PrimedTnt) source;
|
||||
+ List<Vec3> positions = new ArrayList<>(origin.getStacked());
|
||||
+
|
||||
+ // This is a temporary entity that will be used for movement.
|
||||
+ PrimedTnt tnt = new PrimedTnt(level, 0, 0, 0, null);
|
||||
+ AABB bounds = new AABB(x, y, z, x, y, z);
|
||||
+
|
||||
+ origin.entityState().apply(tnt);
|
||||
+
|
||||
+ Vec3 lastMovement = tnt.getDeltaMovement();
|
||||
+ List<Vec3> positions = new ArrayList<>(source.getStacked());
|
||||
+ ExplosionBlockCache[] blockCache = createBlockCache();
|
||||
+
|
||||
+ EntityState entityState = null;
|
||||
+ AABB bounds = new AABB(x, y, z, x, y, z);
|
||||
+ Vec3 lastMovement = source.entityState().momentum();
|
||||
+ int wrapped = 0;
|
||||
+
|
||||
+ for (int i = 0; i < origin.getStacked() && !wasCanceled; ++i) {
|
||||
+ for (int i = 0; i < source.getStacked() && !wasCanceled; ++i) {
|
||||
+ if (i > 0) {
|
||||
+ updatePosition(origin, tnt);
|
||||
+ calculateNextPosition(entityState);
|
||||
+ getToBlow().clear();
|
||||
+ }
|
||||
+
|
||||
+ // block at explosion position
|
||||
+ int blockX = Mth.floor(x);
|
||||
+ int blockY = Mth.floor(y);
|
||||
+ int blockZ = Mth.floor(z);
|
||||
+ // keep track of positions and bounds
|
||||
+ Vec3 position = new Vec3(x, y, z);
|
||||
+ positions.add(position);
|
||||
+ bounds = bounds.minmax(new AABB(position, position));
|
||||
+
|
||||
+ // search for blocks if necessary
|
||||
+ if (wrapped < 7 + 12) {
|
||||
+ getToBlow().clear();
|
||||
+ int blockX = Mth.floor(x);
|
||||
+ int blockY = Mth.floor(y);
|
||||
+ int blockZ = Mth.floor(z);
|
||||
+
|
||||
+ long key = BlockPos.asLong(blockX, blockY, blockZ);
|
||||
+ ExplosionBlockCache center = getOrCacheExplosionBlock(blockX, blockY, blockZ, key, true);
|
||||
@@ -244,28 +245,30 @@ index 0000000000000000000000000000000000000000..4f9880d35347dd008aa2ee6e67f35301
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // keep track of positions and bounds
|
||||
+ positions.add(position);
|
||||
+ bounds = bounds.minmax(new AABB(position, position));
|
||||
+
|
||||
+ Vec3 movement = tnt.getDeltaMovement();
|
||||
+
|
||||
+ // Check if the explosion has wrapped around with swinging on each axis
|
||||
+ if (wrapped < 7) {
|
||||
+ // Check if the explosion has wrapped around with swinging on each axis
|
||||
+ Vec3 movement = source.entityState().momentum();
|
||||
+ if (movement.x == lastMovement.x || movement.x * lastMovement.x < 0) wrapped |= 1;
|
||||
+ if (movement.y == lastMovement.y || movement.y * lastMovement.y < 0) wrapped |= 1 << 1;
|
||||
+ if (movement.z == lastMovement.z || movement.z * lastMovement.z < 0) wrapped |= 1 << 2;
|
||||
+ } else if (getToBlow().isEmpty() && level.sakuraConfig().cannons.explosion.avoidRedundantBlockSearches) {
|
||||
+ wrapped++;
|
||||
+ } else {
|
||||
+ wrapped = 7;
|
||||
+ lastMovement = movement;
|
||||
+ }
|
||||
+
|
||||
+ lastMovement = tnt.getDeltaMovement();
|
||||
+ boolean isFinalExplosion = i + 1 >= source.getStacked();
|
||||
+
|
||||
+ if (i + 1 < origin.getStacked()) {
|
||||
+ // Possible optimisation here is making our own finalize explosion for this special case.
|
||||
+ // If this is after the explosion event we can take better advantage of protection plugins.
|
||||
+ if (isFinalExplosion || !getToBlow().isEmpty()) {
|
||||
+ locateAndImpactEntities(positions, bounds, blockCache);
|
||||
+ bounds = new AABB(position, position);
|
||||
+ positions.clear();
|
||||
+ }
|
||||
+
|
||||
+ if (!isFinalExplosion) {
|
||||
+ BlockPos.MutableBlockPos mbp = new BlockPos.MutableBlockPos();
|
||||
+ impactEntityIdle(tnt, new Entity[0], position, 1, radius * 2.0f, mbp, blockCache);
|
||||
+
|
||||
+ // Calculate next source velocity
|
||||
+ entityState = calculateNextVelocity(position, mbp, blockCache);
|
||||
+
|
||||
+ // The purpose of this is to make sure papers blockCache doesn't become
|
||||
+ // outdated by flushing the map and removing stale entries from the recent
|
||||
@@ -273,41 +276,50 @@ index 0000000000000000000000000000000000000000..4f9880d35347dd008aa2ee6e67f35301
|
||||
+ // movement and then start moving without blocks this may break stuff to
|
||||
+ // fix it see the note above or add a boolean to mark the cache as dirty
|
||||
+ // outside this loop and then invalidate before the final impact entities.
|
||||
+ if (!getToBlow().isEmpty() && tnt.getDeltaMovement().lengthSqr() <= 64.0) {
|
||||
+ if (!getToBlow().isEmpty()) {
|
||||
+ invalidateBlockCache(blockCache);
|
||||
+ }
|
||||
+
|
||||
+ // could it be viable to have a configuration option to only
|
||||
+ // call finalize explosion when blocks are found
|
||||
+ // may affect plugins that need exact explosion positions
|
||||
+ // Could be viable in the future to have a configuration option to reduce explosion events
|
||||
+ super.finalizeExplosion(false);
|
||||
+ ((ServerLevel) level).notifyPlayersOfExplosion(x, y, z, radius, this);
|
||||
+ } else {
|
||||
+ locateAndImpactEntities(positions, bounds, blockCache);
|
||||
+
|
||||
+ // Update wrapped, this is for tracking swinging and if blocks are found
|
||||
+ if (getToBlow().isEmpty() && level.sakuraConfig().cannons.explosion.avoidRedundantBlockSearches) {
|
||||
+ wrapped++;
|
||||
+ } else {
|
||||
+ wrapped = 7;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ clearBlockCache();
|
||||
+ }
|
||||
+
|
||||
+ private void updatePosition(PrimedTnt origin, PrimedTnt tnt) {
|
||||
+ boolean originMoved = !origin.position().equals(tnt.position());
|
||||
+ private void calculateNextPosition(EntityState entityState) {
|
||||
+ if (source instanceof PrimedTnt tnt) {
|
||||
+ tnt.setFuse(100);
|
||||
+ }
|
||||
+
|
||||
+ origin.setFuse(100);
|
||||
+ tnt.storeEntityState();
|
||||
+ tnt.entityState().apply(origin);
|
||||
+ boolean moved = !source.entityState().position().equals(source.position());
|
||||
+ entityState.apply(source);
|
||||
+ source.storeEntityState();
|
||||
+
|
||||
+ // We have to check delta movement otherwise this optimisation can break reversing tnt.
|
||||
+ // If origin was shot upwards to a block then falls in the explosion tick it will swing
|
||||
+ // and origin and tnt will be in the same position every other tnt while swinging.
|
||||
+ if (!getToBlow().isEmpty() || tnt.getDeltaMovement().lengthSqr() <= 64.0 || originMoved) {
|
||||
+ origin.tick();
|
||||
+ if (!getToBlow().isEmpty() || source.getDeltaMovement().lengthSqr() <= 65.16525625 || moved) {
|
||||
+ source.tick();
|
||||
+ }
|
||||
+
|
||||
+ // update explosion position
|
||||
+ x = origin.getX();
|
||||
+ y = origin.getY(0.0625);
|
||||
+ z = origin.getZ();
|
||||
+ x = source.getX();
|
||||
+ y = source.getY();
|
||||
+ z = source.getZ();
|
||||
+ }
|
||||
+
|
||||
+ private EntityState calculateNextVelocity(Vec3 position, BlockPos.MutableBlockPos mbp, ExplosionBlockCache[] blockCache) {
|
||||
+ PrimedTnt tnt = new PrimedTnt(EntityType.TNT, level);
|
||||
+ source.entityState().apply(tnt);
|
||||
+ impactEntityIdle(tnt, new Entity[0], position, 1, radius * 2.0f, mbp, blockCache);
|
||||
+ return EntityState.of(tnt);
|
||||
+ }
|
||||
+
|
||||
+ private void locateAndImpactEntities(List<Vec3> positions, AABB bb, ExplosionBlockCache[] blockCache) {
|
||||
|
||||
@@ -36,10 +36,19 @@ index ae2eede559bd9fe7e500ce180f2ac102a95d3856..7ced5ae768cbea9ee0a7bab2365fbaef
|
||||
if (xSmaller && z != 0.0) {
|
||||
z = performAABBCollisionsZ(axisalignedbb, z, aabbs);
|
||||
diff --git a/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java b/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java
|
||||
index 4f9880d35347dd008aa2ee6e67f35301ff37a4c0..79d5cd8f90fda2390a64c2d1e0cfca6b66ad83ac 100644
|
||||
index 8a8b4169c8928459f6b51150bd8e67d0a309ca08..a291516ec7bdb9d8b840f41ca52e6bbaf8e2e08a 100644
|
||||
--- a/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java
|
||||
+++ b/src/main/java/me/samsuik/sakura/explosion/SakuraExplosion.java
|
||||
@@ -244,10 +244,17 @@ public class SakuraExplosion extends Explosion {
|
||||
@@ -163,7 +163,7 @@ public class SakuraExplosion extends Explosion {
|
||||
|
||||
// update explosion position
|
||||
x = source.getX();
|
||||
- y = source.getY();
|
||||
+ y = physics.before(1_10_0) ? source.getY() + (double) 0.49f : source.getY(0.0625D);
|
||||
z = source.getZ();
|
||||
}
|
||||
|
||||
@@ -256,10 +256,17 @@ public class SakuraExplosion extends Explosion {
|
||||
if (distanceFromBottom > 1.0) continue;
|
||||
|
||||
double x = entity.getX() - pos.x;
|
||||
@@ -58,7 +67,7 @@ index 4f9880d35347dd008aa2ee6e67f35301ff37a4c0..79d5cd8f90fda2390a64c2d1e0cfca6b
|
||||
if (distance == 0.0D) continue;
|
||||
|
||||
x /= distance;
|
||||
@@ -292,10 +299,17 @@ public class SakuraExplosion extends Explosion {
|
||||
@@ -304,10 +311,17 @@ public class SakuraExplosion extends Explosion {
|
||||
|
||||
if (distanceFromBottom <= 1.0) {
|
||||
double x = entity.getX() - pos.x;
|
||||
|
||||
Reference in New Issue
Block a user