From 523e8d98c46b9f7b9e8a71d3dbde14b686f140d6 Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Thu, 11 Jul 2024 11:44:10 -0700 Subject: [PATCH] Changes made while porting collision patch to Paper 1. Need a better solution for EntityMixin block/fire collision 2. Fixed inconsistent Vanilla behavior for ExplosionMixin Mostly revolved around the explosion intensity calculator, as well as the damage calculator 3. Optimise ExplosionMixin to not call getSeenPercent twice, which is a new "feature" of 1.21 4. Optimise VoxelShapeMixin#toAabbsUncached() The regular forAllBoxes method on VoxelShape will incur indirection costs due to the virtual method invoke on the coordinate retrieval as well as on the consumer itself --- .../mixin/collisions/EntityMixin.java | 1 + .../mixin/collisions/ExplosionMixin.java | 47 +++++++++++-------- .../mixin/collisions/VoxelShapeMixin.java | 27 +++++++++-- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java index 4407278c..bd205722 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/EntityMixin.java @@ -202,6 +202,7 @@ public Stream shortCircuitStreamLogic(final Level level, final AABB ) ) public void checkInsideBlocks(final Entity instance) { + // TODO unfuck these changes final AABB boundingBox = this.getBoundingBox(); final BlockPos.MutableBlockPos tempPos = new BlockPos.MutableBlockPos(); diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java index 6e5738af..962bd49c 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/ExplosionMixin.java @@ -468,30 +468,39 @@ public void explode() { double distZ = entity.getZ() - this.z; final double distMag = Math.sqrt(distX * distX + distY * distY + distZ * distZ); - if (distMag != 0.0) { - distX /= distMag; - distY /= distMag; - distZ /= distMag; + if (distMag == 0.0) { + continue; + } - // route to new visible fraction calculation, using the existing block cache - final double intensityFraction = (1.0 - normalizedDistanceToCenter) * (double)this.getSeenFraction(center, entity, blockCache, blockPos); + distX /= distMag; + distY /= distMag; + distZ /= distMag; + + // route to new visible fraction calculation, using the existing block cache + final double seenFraction = (double)this.getSeenFraction(center, entity, blockCache, blockPos); + if (this.damageCalculator.shouldDamageEntity((Explosion)(Object)this, entity)) { + // inline getEntityDamageAmount so that we can avoid double calling getSeenPercent, which is the MOST + // expensive part of this loop!!!! + final double factor = (1.0 - normalizedDistanceToCenter) * seenFraction; + entity.hurt(this.damageSource, (float)((factor * factor + factor) / 2.0 * 7.0 * diameter + 1.0)); + } - entity.hurt(this.damageSource, (float)((int)((intensityFraction * intensityFraction + intensityFraction) / 2.0 * 7.0 * diameter + 1.0))); + final double intensityFraction = (1.0 - normalizedDistanceToCenter) * seenFraction * (double)this.damageCalculator.getKnockbackMultiplier(entity); - final double knockbackFraction; - if (entity instanceof LivingEntity livingEntity) { - knockbackFraction = intensityFraction * (1.0 - livingEntity.getAttributeValue(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE)); - } else { - knockbackFraction = intensityFraction; - } - final Vec3 knockback = new Vec3(distX * knockbackFraction, distY * knockbackFraction, distZ * knockbackFraction); - entity.setDeltaMovement(entity.getDeltaMovement().add(knockback)); + final double knockbackFraction; + if (entity instanceof LivingEntity livingEntity) { + knockbackFraction = intensityFraction * (1.0 - livingEntity.getAttributeValue(Attributes.EXPLOSION_KNOCKBACK_RESISTANCE)); + } else { + knockbackFraction = intensityFraction; + } - if (entity instanceof Player player) { - if (!player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) { - this.hitPlayers.put(player, knockback); - } + final Vec3 knockback = new Vec3(distX * knockbackFraction, distY * knockbackFraction, distZ * knockbackFraction); + entity.setDeltaMovement(entity.getDeltaMovement().add(knockback)); + + if (entity instanceof Player player) { + if (!player.isSpectator() && (!player.isCreative() || !player.getAbilities().flying)) { + this.hitPlayers.put(player, knockback); } } } diff --git a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/VoxelShapeMixin.java b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/VoxelShapeMixin.java index 78174b58..e589e913 100644 --- a/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/VoxelShapeMixin.java +++ b/src/main/java/ca/spottedleaf/moonrise/mixin/collisions/VoxelShapeMixin.java @@ -121,6 +121,7 @@ public abstract class VoxelShapeMixin implements CollisionVoxelShape { return this.rootCoordinatesZ; } + @Unique private static double[] extractRawArray(final DoubleList list) { if (list instanceof DoubleArrayList rawList) { final double[] raw = rawList.elements(); @@ -422,9 +423,27 @@ private List toAabbsUncached() { if (this.singleAABBRepresentation != null) { ret.add(this.singleAABBRepresentation); } else { - this.forAllBoxes((minX, minY, minZ, maxX, maxY, maxZ) -> { - ret.add(new AABB(minX, minY, minZ, maxX, maxY, maxZ)); - }); + final double[] coordsX = this.rootCoordinatesX; + final double[] coordsY = this.rootCoordinatesY; + final double[] coordsZ = this.rootCoordinatesZ; + + final double offX = this.offsetX; + final double offY = this.offsetY; + final double offZ = this.offsetZ; + + this.shape.forAllBoxes((final int minX, final int minY, final int minZ, + final int maxX, final int maxY, final int maxZ) -> { + ret.add(new AABB( + coordsX[minX] + offX, + coordsY[minY] + offY, + coordsZ[minZ] + offZ, + + + coordsX[maxX] + offX, + coordsY[maxY] + offY, + coordsZ[maxZ] + offZ + )); + }, true); } // cache result @@ -525,7 +544,7 @@ private boolean computeFullBlock() { } @Override - public boolean moonrise$isFullBlock() { + public final boolean moonrise$isFullBlock() { final Boolean ret = this.isFullBlock; if (ret != null) {