Skip to content

Commit 550e644

Browse files
committed
Make BlockBreakingMovementBehaviourMixin more robust
Instead of checking the current actor origin against the current block being broken, we check the current actor origin against the origin when it started breaking the block. This ensures that no matter how large of an area the actor is breaking (IE. rollers, drills from addons that break in an absurd 10x10 area, etc), breaking will still occur until the actor is moved suffeciently far away.
1 parent 22b8ce9 commit 550e644

1 file changed

Lines changed: 50 additions & 29 deletions

File tree

neoforge/src/main/java/dev/ryanhcode/sable/neoforge/mixin/compatibility/create/behaviour_compatibility/block_breaking_behaviour/BlockBreakingMovementBehaviourMixin.java

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@
77
import com.simibubi.create.content.kinetics.base.BlockBreakingMovementBehaviour;
88
import dev.ryanhcode.sable.ActiveSableCompanion;
99
import dev.ryanhcode.sable.Sable;
10+
import dev.ryanhcode.sable.companion.math.JOMLConversion;
1011
import dev.ryanhcode.sable.neoforge.mixinhelper.compatibility.create.block_breakers.SubLevelBlockBreakingUtility;
1112
import dev.ryanhcode.sable.sublevel.SubLevel;
13+
import net.createmod.catnip.math.VecHelper;
14+
import net.createmod.catnip.nbt.NBTHelper;
1215
import net.minecraft.core.BlockPos;
1316
import net.minecraft.nbt.CompoundTag;
1417
import net.minecraft.nbt.NbtUtils;
18+
import net.minecraft.nbt.Tag;
19+
import net.minecraft.world.damagesource.DamageSource;
1520
import net.minecraft.world.level.Level;
1621
import net.minecraft.world.level.block.state.BlockState;
1722
import net.minecraft.world.phys.Vec3;
23+
import org.joml.Vector3d;
1824
import org.spongepowered.asm.mixin.Mixin;
1925
import org.spongepowered.asm.mixin.Shadow;
2026
import org.spongepowered.asm.mixin.injection.At;
@@ -50,45 +56,60 @@ public abstract class BlockBreakingMovementBehaviourMixin implements MovementBeh
5056
original.call(context, breakingPosWSublevel);
5157
}
5258
}
53-
}
5459

55-
@Inject(method = "tick", at = @At("HEAD"), cancellable = true)
56-
public void sable$testBreakingPosDist(final MovementContext context, final CallbackInfo ci) {
57-
final CompoundTag data = context.data;
58-
if (data.contains("BreakingPos") || data.contains("LastPos")) {
59-
final BlockPos blockPos = NbtUtils.readBlockPos(data, "BreakingPos").orElseGet(() -> NbtUtils.readBlockPos(data, "LastPos").orElse(null));
60+
//make sure we're actually starting to break something
61+
if (context.stall && (context.data.contains("BreakingPos"))) {
62+
final Vector3d checkPos = JOMLConversion.toJOML(context.position);
6063

61-
if (blockPos != null) {
62-
final Vec3 localCenter = context.localPos.getCenter();
64+
//project our position into the real world
65+
final SubLevel parentSublevel = Sable.HELPER.getContaining(context.world, context.position);
66+
if (parentSublevel != null) {
67+
parentSublevel.logicalPose().transformPosition(checkPos);
68+
}
69+
70+
//project our position into the target's plot
71+
final SubLevel targetSublevel = Sable.HELPER.getContaining(context.world, NbtUtils.readBlockPos(context.data, "BreakingPos").orElseThrow());
72+
if (targetSublevel != null) {
73+
targetSublevel.logicalPose().transformPositionInverse(checkPos);
74+
}
6375

64-
Vec3 sublevelLocalCenter = context.contraption.entity.toGlobalVector(localCenter, 1);
65-
Vec3 targetCenter = blockPos.getCenter();
76+
//save the current projected position to check movement distance against
77+
context.data.put("ProjectedPos", VecHelper.writeNBT(JOMLConversion.toMojang(checkPos)));
78+
}
79+
}
6680

67-
final ActiveSableCompanion helper = Sable.HELPER;
68-
final SubLevel parentSublevel = helper.getContaining(context.world, context.contraption.anchor);
69-
final SubLevel targetSubLevel = helper.getContaining(context.world, blockPos);
81+
@Inject(method = "cancelStall", at = @At("TAIL"))
82+
public void sable$removeProjected(final MovementContext context, final CallbackInfo ci) {
83+
context.data.remove("ProjectedPos");
84+
}
7085

71-
if (parentSublevel != null) {
72-
sublevelLocalCenter = parentSublevel.logicalPose().transformPosition(sublevelLocalCenter);
73-
}
86+
@Inject(method = "tick", at = @At("HEAD"), cancellable = true)
87+
public void sable$testProjectedPosDist(final MovementContext context, final CallbackInfo ci) {
88+
final CompoundTag data = context.data;
7489

75-
if (targetSubLevel != null) {
76-
targetCenter = targetSubLevel.logicalPose().transformPosition(targetCenter);
77-
}
90+
//kind of a work-around to not require injecting into every place where BreakingPos is removed.
91+
if (!context.data.contains("BreakingPos")) {
92+
data.remove("ProjectedPos");
93+
return;
94+
}
7895

79-
if (sublevelLocalCenter.distanceToSqr(targetCenter) > 2 * 2) {
80-
data.remove("Progress");
81-
data.remove("TicksUntilNextProgress");
82-
data.remove("BreakingPos");
83-
data.remove("LastPos");
84-
data.remove("WaitingTicks");
96+
final Vec3 sublevelLocalCenter = context.contraption.entity.toGlobalVector(context.localPos.getCenter(), 1);
97+
if (data.contains("ProjectedPos") && Sable.HELPER.distanceSquaredWithSubLevels(context.world, VecHelper.readNBT(data.getList("ProjectedPos", Tag.TAG_DOUBLE)), sublevelLocalCenter) > 2*2) {
98+
final BlockPos blockPos = NbtUtils.readBlockPos(data, "BreakingPos").orElse(null);
8599

86-
context.stall = false;
87-
context.world.destroyBlockProgress(data.getInt("BreakerId"), blockPos, -1);
100+
data.remove("Progress");
101+
data.remove("TicksUntilNextProgress");
102+
data.remove("BreakingPos");
103+
data.remove("LastPos");
104+
data.remove("WaitingTicks");
105+
data.remove("ProjectedPos");
88106

89-
ci.cancel();
90-
}
107+
context.stall = false;
108+
if (blockPos != null) {
109+
context.world.destroyBlockProgress(data.getInt("BreakerId"), blockPos, -1);
91110
}
111+
112+
ci.cancel();
92113
}
93114
}
94115
}

0 commit comments

Comments
 (0)