Skip to content

Commit 8a115e7

Browse files
committed
use server rotation when placing and add chest post processing to ignore unfinished double chests
1 parent 49e13c1 commit 8a115e7

File tree

16 files changed

+150
-45
lines changed

16 files changed

+150
-45
lines changed

src/main/java/com/lambda/mixin/entity/EntityMixin.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717

1818
package com.lambda.mixin.entity;
1919

20-
import com.lambda.Lambda;
2120
import com.lambda.event.EventFlow;
2221
import com.lambda.event.events.EntityEvent;
2322
import com.lambda.event.events.PlayerEvent;
@@ -42,6 +41,8 @@
4241
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
4342
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
4443

44+
import static com.lambda.Lambda.getMc;
45+
4546
@Mixin(Entity.class)
4647
public abstract class EntityMixin {
4748
@Shadow
@@ -56,7 +57,7 @@ public void move(MovementType movementType, Vec3d movement) {
5657
*/
5758
@WrapOperation(method = "updateVelocity", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getYaw()F"))
5859
public float velocityYaw(Entity entity, Operation<Float> original) {
59-
if ((Object) this != Lambda.getMc().player) return original.call(entity);
60+
if ((Object) this != getMc().player) return original.call(entity);
6061

6162
Float y = RotationManager.getMovementYaw();
6263
if (y == null) return original.call(entity);
@@ -75,7 +76,7 @@ public float velocityYaw(Entity entity, Operation<Float> original) {
7576
@WrapOperation(method = "getRotationVec", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getYaw(F)F"))
7677
float fixDirectionYaw(Entity entity, float tickDelta, Operation<Float> original) {
7778
Vec2d rot = RotationManager.getRotationForVector(tickDelta);
78-
if (entity != Lambda.getMc().player || rot == null) return original.call(entity, tickDelta);
79+
if (entity != getMc().player || rot == null) return original.call(entity, tickDelta);
7980

8081
return (float) rot.getX();
8182
}
@@ -91,7 +92,7 @@ float fixDirectionYaw(Entity entity, float tickDelta, Operation<Float> original)
9192
@WrapOperation(method = "getRotationVec", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPitch(F)F"))
9293
float fixDirectionPitch(Entity entity, float tickDelta, Operation<Float> original) {
9394
Vec2d rot = RotationManager.getRotationForVector(tickDelta);
94-
if (entity != Lambda.getMc().player || rot == null) return original.call(entity, tickDelta);
95+
if (entity != getMc().player || rot == null) return original.call(entity, tickDelta);
9596

9697
return (float) rot.getY();
9798
}
@@ -107,7 +108,7 @@ float fixDirectionPitch(Entity entity, float tickDelta, Operation<Float> origina
107108
@WrapOperation(method = "getRotationVector()Lnet/minecraft/util/math/Vec3d;", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getYaw()F"))
108109
float fixDirectionYaw2(Entity entity, Operation<Float> original) {
109110
Vec2d rot = RotationManager.getRotationForVector(1.0);
110-
if (entity != Lambda.getMc().player || rot == null) return original.call(entity);
111+
if (entity != getMc().player || rot == null) return original.call(entity);
111112

112113
return (float) rot.getX();
113114
}
@@ -123,7 +124,7 @@ float fixDirectionYaw2(Entity entity, Operation<Float> original) {
123124
@WrapOperation(method = "getRotationVector()Lnet/minecraft/util/math/Vec3d;", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPitch()F"))
124125
float fixDirectionPitch2(Entity entity, Operation<Float> original) {
125126
Vec2d rot = RotationManager.getRotationForVector(1.0);
126-
if (entity != Lambda.getMc().player || rot == null) return original.call(entity);
127+
if (entity != getMc().player || rot == null) return original.call(entity);
127128

128129
return (float) rot.getY();
129130
}
@@ -161,8 +162,8 @@ private boolean wrapSetPitch(Entity instance, float yaw) {
161162

162163
@Inject(method = "isSprinting()Z", at = @At("HEAD"), cancellable = true)
163164
private void injectIsSprinting(CallbackInfoReturnable<Boolean> cir) {
164-
var player = Lambda.getMc().player;
165-
if ((Object) this != Lambda.getMc().player) return;
165+
var player = getMc().player;
166+
if ((Object) this != getMc().player) return;
166167
if (ElytraFly.INSTANCE.isEnabled() && ElytraFly.getMode() == ElytraFly.FlyMode.Bounce && player.isGliding()) cir.setReturnValue(true);
167168
}
168169

@@ -172,4 +173,9 @@ private void injectGetPose(CallbackInfoReturnable<EntityPose> cir) {
172173
if (!(entity instanceof ClientPlayerEntity player)) return;
173174
if (ElytraFly.INSTANCE.isEnabled() && ElytraFly.getMode() == ElytraFly.FlyMode.Bounce && player.isGliding()) cir.setReturnValue(EntityPose.GLIDING);
174175
}
176+
177+
@ModifyExpressionValue(method = "getHorizontalFacing", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getYaw()F"))
178+
private float modifyGetYaw(float original) {
179+
return (Object) this == getMc().player ? RotationManager.getServerRotation().getYawF() : original;
180+
}
175181
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2026 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.mixin.world;
19+
20+
import com.lambda.interaction.managers.rotating.RotationManager;
21+
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
22+
import net.minecraft.entity.Entity;
23+
import net.minecraft.util.math.Direction;
24+
import org.spongepowered.asm.mixin.Mixin;
25+
import org.spongepowered.asm.mixin.injection.At;
26+
27+
import static com.lambda.Lambda.getMc;
28+
29+
@Mixin(Direction.class)
30+
public class DirectionMixin {
31+
@ModifyExpressionValue(method = "getEntityFacingOrder", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getYaw(F)F"))
32+
private static float modifyGetYaw(float original, Entity entity) {
33+
return entity == getMc().player ? RotationManager.getServerRotation().getYawF() : original;
34+
}
35+
36+
@ModifyExpressionValue(method = "getEntityFacingOrder", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getPitch(F)F"))
37+
private static float modifyGetPitch(float original, Entity entity) {
38+
return entity == getMc().player ? RotationManager.getServerRotation().getPitchF() : original;
39+
}
40+
}

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/PlacementProcessor.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,15 @@ interface StateProcessor {
3434
}
3535

3636
interface PropertyPreProcessor {
37-
fun acceptsState(targetState: BlockState): Boolean
37+
fun acceptsState(state: BlockState, targetState: BlockState): Boolean
3838

3939
context(safeContext: SafeContext)
4040
fun PreProcessingInfoAccumulator.preProcess(state: BlockState, targetState: BlockState, pos: BlockPos)
4141
}
4242

4343
interface PropertyPostProcessor {
4444
fun acceptsState(state: BlockState, targetState: BlockState): Boolean
45-
fun PreProcessingInfoAccumulator.preProcess(state: BlockState, targetState: BlockState)
45+
46+
context(safeContext: SafeContext)
47+
fun PreProcessingInfoAccumulator.preProcess(state: BlockState, targetState: BlockState, pos: BlockPos)
4648
}

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/ProcessorRegistry.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -147,26 +147,26 @@ object ProcessorRegistry : Loadable {
147147
context(safeContext: SafeContext)
148148
private fun preProcess(pos: BlockPos, state: BlockState, targetState: BlockState, itemStack: ItemStack) =
149149
PreProcessingInfoAccumulator(targetState, itemStack.item).run {
150-
val stateProcessing = stateProcessors.any { processor ->
151-
processor.acceptsState(state, targetState).also { accepted ->
152-
if (accepted)
153-
with(processor) { preProcess(state, targetState, pos) }
150+
stateProcessors.forEach { processor ->
151+
if (processor.acceptsState(state, targetState)) {
152+
with(processor) { preProcess(state, targetState, pos) }
154153
}
155154
}
156-
if (!stateProcessing && !omitInteraction) {
155+
if (!omitInteraction) {
157156
if (state.block != expectedState.block) {
158157
if (!state.isReplaceable) return@run null
159158
propertyPreProcessors.forEach { processor ->
160-
if (processor.acceptsState(targetState))
159+
if (processor.acceptsState(state, expectedState)) {
161160
with(processor) { preProcess(state, expectedState, pos) }
161+
}
162162
}
163163
} else {
164164
propertyPostProcessors.forEach { processor ->
165165
if (processor.acceptsState(state, expectedState)) {
166-
with(processor) { preProcess(state, expectedState) }
166+
with(processor) { preProcess(state, expectedState, pos) }
167167
}
168168
}
169-
if (!state.matches(targetState, ignore)) return@run null
169+
if (!state.matches(expectedState, ignore)) return@run null
170170
}
171171
}
172172
complete()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
* Copyright 2026 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.interaction.construction.simulation.processing.preprocessors.property.placement.post
19+
20+
import com.lambda.context.SafeContext
21+
import com.lambda.interaction.construction.simulation.processing.PreProcessingInfoAccumulator
22+
import com.lambda.interaction.construction.simulation.processing.PropertyPostProcessor
23+
import com.lambda.util.BlockUtils.blockState
24+
import net.minecraft.block.BlockState
25+
import net.minecraft.block.ChestBlock
26+
import net.minecraft.block.enums.ChestType
27+
import net.minecraft.state.property.Properties
28+
import net.minecraft.util.math.BlockPos
29+
30+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
31+
@Suppress("unused")
32+
object ChestPostProcessor : PropertyPostProcessor {
33+
override fun acceptsState(state: BlockState, targetState: BlockState) =
34+
state.block is ChestBlock && state.block === targetState.block &&
35+
Properties.CHEST_TYPE in state && Properties.HORIZONTAL_FACING in state &&
36+
state.get(Properties.HORIZONTAL_FACING) == targetState.get(Properties.HORIZONTAL_FACING) &&
37+
state.get(Properties.CHEST_TYPE) != targetState.get(Properties.CHEST_TYPE)
38+
39+
context(safeContext: SafeContext)
40+
override fun PreProcessingInfoAccumulator.preProcess(state: BlockState, targetState: BlockState, pos: BlockPos) {
41+
noCaching()
42+
val targetType = targetState.get(Properties.CHEST_TYPE)
43+
val currentType = state.get(Properties.CHEST_TYPE)
44+
if (currentType != ChestType.SINGLE) return
45+
val currentFacing = state.get(Properties.HORIZONTAL_FACING)
46+
val otherChestDirection = when(targetType) {
47+
ChestType.LEFT -> currentFacing.rotateYClockwise()
48+
else -> currentFacing.rotateYCounterclockwise()
49+
}
50+
val otherChest = safeContext.blockState(pos.offset(otherChestDirection))
51+
if (otherChest.block !is ChestBlock || otherChest.get(Properties.CHEST_TYPE) != ChestType.SINGLE)
52+
addIgnores(Properties.CHEST_TYPE)
53+
}
54+
}

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/preprocessors/property/placement/post/StandardInteractPostProcessor.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@
1717

1818
package com.lambda.interaction.construction.simulation.processing.preprocessors.property.placement.post
1919

20+
import com.lambda.context.SafeContext
2021
import com.lambda.interaction.construction.simulation.processing.PreProcessingInfoAccumulator
2122
import com.lambda.interaction.construction.simulation.processing.ProcessorRegistry.standardInteractProperties
2223
import com.lambda.interaction.construction.simulation.processing.PropertyPostProcessor
2324
import net.minecraft.block.BlockState
25+
import net.minecraft.util.math.BlockPos
2426

2527
// Collected using reflections and then accessed from a collection in ProcessorRegistry
2628
@Suppress("unused")
@@ -30,7 +32,8 @@ object StandardInteractPostProcessor : PropertyPostProcessor {
3032
it in targetState && state.get(it) != targetState.get(it)
3133
}
3234

33-
override fun PreProcessingInfoAccumulator.preProcess(state: BlockState, targetState: BlockState) {
35+
context(safeContext: SafeContext)
36+
override fun PreProcessingInfoAccumulator.preProcess(state: BlockState, targetState: BlockState, pos: BlockPos) {
3437
setItem(null)
3538
setPlacing(false)
3639
}

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/preprocessors/property/placement/pre/AttachmentPreProcessor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import net.minecraft.util.math.Direction
2929
// Collected using reflections and then accessed from a collection in ProcessorRegistry
3030
@Suppress("unused")
3131
object AttachmentPreProcessor : PropertyPreProcessor {
32-
override fun acceptsState(targetState: BlockState) =
32+
override fun acceptsState(state: BlockState, targetState: BlockState) =
3333
Properties.ATTACHMENT in targetState
3434

3535
context(safeContext: SafeContext)

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/preprocessors/property/placement/pre/AxisPreProcessor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import net.minecraft.util.math.BlockPos
2727
// Collected using reflections and then accessed from a collection in ProcessorRegistry
2828
@Suppress("unused")
2929
object AxisPreProcessor : PropertyPreProcessor {
30-
override fun acceptsState(targetState: BlockState) =
30+
override fun acceptsState(state: BlockState, targetState: BlockState) =
3131
Properties.AXIS in targetState
3232

3333
context(safeContext: SafeContext)

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/preprocessors/property/placement/pre/BlockFacePreProcessor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import net.minecraft.util.math.Direction
2929
// Collected using reflections and then accessed from a collection in ProcessorRegistry
3030
@Suppress("unused")
3131
object BlockFacePreProcessor : PropertyPreProcessor {
32-
override fun acceptsState(targetState: BlockState) =
32+
override fun acceptsState(state: BlockState, targetState: BlockState) =
3333
Properties.BLOCK_FACE in targetState
3434

3535
context(safeContext: SafeContext)

src/main/kotlin/com/lambda/interaction/construction/simulation/processing/preprocessors/property/placement/pre/BlockHalfPreProcessor.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import net.minecraft.util.math.Direction
3131
// Collected using reflections and then accessed from a collection in ProcessorRegistry
3232
@Suppress("unused")
3333
object BlockHalfPreProcessor : PropertyPreProcessor {
34-
override fun acceptsState(targetState: BlockState) =
34+
override fun acceptsState(state: BlockState, targetState: BlockState) =
3535
Properties.BLOCK_HALF in targetState
3636

3737
context(safeContext: SafeContext)

0 commit comments

Comments
 (0)