|
12 | 12 | import net.minecraft.world.level.block.entity.BlockEntityType; |
13 | 13 | import net.minecraft.world.level.block.state.BlockState; |
14 | 14 | import net.minecraft.world.phys.AABB; |
| 15 | +import net.minecraft.world.phys.Vec3; |
15 | 16 | import org.spongepowered.asm.mixin.Mixin; |
16 | 17 | import org.spongepowered.asm.mixin.Shadow; |
17 | 18 | import org.spongepowered.asm.mixin.Unique; |
|
22 | 23 | @Mixin(CrushingWheelControllerBlockEntity.class) |
23 | 24 | public abstract class CrushingWheelControllerBlockEntityMixin extends SmartBlockEntity { |
24 | 25 |
|
| 26 | + @Unique |
| 27 | + private static final double SABLE$MAX_CRUSHING_POSITION_DISTANCE_SQR = 64.0; |
| 28 | + |
25 | 29 | @Shadow |
26 | 30 | public Entity processingEntity; |
27 | 31 | @Unique |
28 | 32 | private SubLevel sable$parentSublevel = null; |
| 33 | + @Unique |
| 34 | + private boolean sable$warnedInvalidPosition; |
| 35 | + @Unique |
| 36 | + private boolean sable$warnedInvalidVelocity; |
29 | 37 |
|
30 | 38 | public CrushingWheelControllerBlockEntityMixin(final BlockEntityType<?> typeIn, final BlockPos pos, final BlockState state) { |
31 | 39 | super(typeIn, pos, state); |
@@ -77,4 +85,73 @@ public CrushingWheelControllerBlockEntityMixin(final BlockEntityType<?> typeIn, |
77 | 85 |
|
78 | 86 | return z; |
79 | 87 | } |
| 88 | + |
| 89 | + @WrapOperation( |
| 90 | + method = "tick", |
| 91 | + at = @At( |
| 92 | + value = "INVOKE", |
| 93 | + target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V" |
| 94 | + ), |
| 95 | + require = 1, |
| 96 | + allow = 1 |
| 97 | + ) |
| 98 | + public void sable$transformCrushingVelocity(final Entity instance, final Vec3 localVelocity, final Operation<Void> original) { |
| 99 | + if (this.sable$parentSublevel == null) { |
| 100 | + original.call(instance, localVelocity); |
| 101 | + return; |
| 102 | + } |
| 103 | + |
| 104 | + final Vec3 worldVelocity = this.sable$parentSublevel.logicalPose().transformNormal(localVelocity); |
| 105 | + if (!sable$isFinite(worldVelocity)) { |
| 106 | + if (!this.sable$warnedInvalidVelocity) { |
| 107 | + this.sable$warnedInvalidVelocity = true; |
| 108 | + Sable.LOGGER.error( |
| 109 | + "Invalid crushing-wheel velocity transform at {} for entity {}: local={}, transformed={}", |
| 110 | + this.getBlockPos(), instance.getUUID(), localVelocity, worldVelocity |
| 111 | + ); |
| 112 | + } |
| 113 | + original.call(instance, Vec3.ZERO); |
| 114 | + return; |
| 115 | + } |
| 116 | + |
| 117 | + original.call(instance, worldVelocity); |
| 118 | + } |
| 119 | + |
| 120 | + @WrapOperation( |
| 121 | + method = "tick", |
| 122 | + at = @At( |
| 123 | + value = "INVOKE", |
| 124 | + target = "Lnet/minecraft/world/entity/Entity;setPos(DDD)V" |
| 125 | + ), |
| 126 | + require = 2, |
| 127 | + allow = 2 |
| 128 | + ) |
| 129 | + public void sable$transformCrushingPosition(final Entity instance, final double localX, final double localY, final double localZ, final Operation<Void> original) { |
| 130 | + if (this.sable$parentSublevel == null) { |
| 131 | + original.call(instance, localX, localY, localZ); |
| 132 | + return; |
| 133 | + } |
| 134 | + |
| 135 | + final Vec3 localPosition = new Vec3(localX, localY, localZ); |
| 136 | + final Vec3 worldPosition = this.sable$parentSublevel.logicalPose().transformPosition(localPosition); |
| 137 | + final boolean invalid = !sable$isFinite(worldPosition) |
| 138 | + || worldPosition.distanceToSqr(instance.position()) > SABLE$MAX_CRUSHING_POSITION_DISTANCE_SQR; |
| 139 | + if (invalid) { |
| 140 | + if (!this.sable$warnedInvalidPosition) { |
| 141 | + this.sable$warnedInvalidPosition = true; |
| 142 | + Sable.LOGGER.error( |
| 143 | + "Blocked unsafe crushing-wheel position at {} for entity {}: local={}, transformed={}, current={}", |
| 144 | + this.getBlockPos(), instance.getUUID(), localPosition, worldPosition, instance.position() |
| 145 | + ); |
| 146 | + } |
| 147 | + return; |
| 148 | + } |
| 149 | + |
| 150 | + original.call(instance, worldPosition.x, worldPosition.y, worldPosition.z); |
| 151 | + } |
| 152 | + |
| 153 | + @Unique |
| 154 | + private static boolean sable$isFinite(final Vec3 vector) { |
| 155 | + return Double.isFinite(vector.x) && Double.isFinite(vector.y) && Double.isFinite(vector.z); |
| 156 | + } |
80 | 157 | } |
0 commit comments