Skip to content

Commit fd7dbf1

Browse files
committed
Release 3.3.10
1 parent 530514c commit fd7dbf1

8 files changed

Lines changed: 115 additions & 78 deletions

File tree

v1_21/src/main/java/me/aleksilassila/litematica/printer/v1_21/Printer.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,6 @@ public boolean onGameTick() {
104104
}
105105

106106
List<BlockPos> positions = getReachablePositions();
107-
boolean didPlace = false;
108-
boolean acceptsMoreActions = false;
109107

110108
if (PrinterConfig.BLOCK_TIMEOUT.getIntegerValue() != 0) {
111109
positions = positions.stream().filter((pos) -> blockPosTimeout.stream().noneMatch((entry) -> entry.pos.equals(pos))).toList(); // From block timeout. Don't place already placed blocks.
@@ -118,20 +116,10 @@ public boolean onGameTick() {
118116

119117
Guide[] guides = interactionGuides.getInteractionGuides(state);
120118

121-
BlockHitResult result = RayTraceUtils.traceToSchematicWorld(player, 10, true, true);
122-
boolean isCurrentlyLookingSchematic = result != null && result.getBlockPos().equals(position);
123-
124119
for (Guide guide : guides) {
125120
if (guide.canExecute(player)) {
126-
// System.out.println("Executing Guide:" + guide);
127121
List<Action> actions = guide.execute(player);
128122
actionHandler.addActions(actions.toArray(Action[]::new));
129-
// actions.forEach((action) -> {
130-
// if (action instanceof InteractActionImpl a1) {
131-
// // InfoUtils.sendVanillaMessage(Text.literal("InteractActionImpl: " + a1));
132-
// mc.inGameHud.getChatHud().addMessage(Text.literal("InteractActionImpl: " + a1.context.getBlockPos()));
133-
// }
134-
// });
135123
return true;
136124
}
137125
if (guide.skipOtherGuides()) continue findBlock;

v1_21/src/main/java/me/aleksilassila/litematica/printer/v1_21/config/PrinterConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public static PrinterConfig getInstance() {
5858
public static final ConfigBoolean PRINTER_ALLOW_NONE_EXACT_STATES = new ConfigBoolean("printerAllowNoneExactStates", false, "Allow none exact block states to be placed.\nThis includes things like lichen, muchroom stems, etc.");
5959
public static final ConfigBoolean PRINTER_DISABLE_IN_GUIS = new ConfigBoolean("printerDisableInGuis", true, "Disable the printer in GUIs.");
6060
public static final ConfigBoolean PRINTER_AIRPLACE = new ConfigBoolean("printerAirPlace", false, "Place blocks in the air.");
61+
public static final ConfigBoolean PRINTER_AIRPLACE_ONLY = new ConfigBoolean("printerAirPlaceOnly", false, "Attempt to air place only when air place is enabled.");
62+
public static final ConfigBoolean PRINTER_AIRPLACE_OFFHAND_SLOT_SUPPRESS = new ConfigBoolean("printerAirPlaceOffhandSlotSuppress", true, "Suppress off-hand slot updates when air placing. Turn off when there are de-sync issues in the off-hand slot.");
6163
public static final ConfigDouble PRINTER_AIRPLACE_RANGE = new ConfigDouble("printerAirPlaceRange", 5, 0, 10, "Range at which the printer can air place at");
6264
public static final ConfigBoolean PRINTER_AIRPLACE_FLOATING_ONLY = new ConfigBoolean("printerAirPlaceFloatingOnly", false, "Only attempt to air place if the block position is surrounded by air.");
6365
public static final ConfigInteger PRINTER_MIN_INACTIVE_TIME_AIR_PLACE = new ConfigInteger("printerMinInactiveTimeAirPlace", 5, "Minimum time in ticks to wait before placing a block in the air.");
@@ -89,6 +91,8 @@ public ImmutableList<IConfigBase> getOptions() {
8991
list.add(PRINTER_ALLOW_NONE_EXACT_STATES);
9092
list.add(PRINTER_DISABLE_IN_GUIS);
9193
list.add(PRINTER_AIRPLACE);
94+
list.add(PRINTER_AIRPLACE_ONLY);
95+
list.add(PRINTER_AIRPLACE_OFFHAND_SLOT_SUPPRESS);
9296
list.add(PRINTER_AIRPLACE_RANGE);
9397
list.add(PRINTER_AIRPLACE_FLOATING_ONLY);
9498
list.add(PRINTER_MIN_INACTIVE_TIME_AIR_PLACE);

v1_21/src/main/java/me/aleksilassila/litematica/printer/v1_21/guides/placement/GeneralPlacementGuide.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -273,18 +273,18 @@ public PrinterPlacementContext getPlacementContext(ClientPlayerEntity player) {
273273
}
274274
}
275275
continue;
276-
}
277-
278-
BlockHitResult hitResult = new BlockHitResult(blockHit, side.getOpposite(), neighborPos, false);
279-
PrinterPlacementContext context = new PrinterPlacementContext(player, hitResult, requiredItem, slot, relativeDirection, requiresShift);
280-
context.canStealth = true;
281-
BlockState result = getRequiredItemAsBlock(player)
282-
.orElse(targetState.getBlock())
283-
.getPlacementState(context); // FIXME torch shift clicks another torch and getPlacementState is the clicked block, which is true
284-
285-
if (result != null && (statesEqual(result, targetState) || correctChestPlacement(targetState, result))) {
286-
contextCache = context;
287-
return context;
276+
} else {
277+
BlockHitResult hitResult = new BlockHitResult(blockHit, side.getOpposite(), neighborPos, false);
278+
PrinterPlacementContext context = new PrinterPlacementContext(player, hitResult, requiredItem, slot, relativeDirection, requiresShift);
279+
context.canStealth = true;
280+
BlockState result = getRequiredItemAsBlock(player)
281+
.orElse(targetState.getBlock())
282+
.getPlacementState(context); // FIXME torch shift clicks another torch and getPlacementState is the clicked block, which is true
283+
284+
if (result != null && (statesEqual(result, targetState) || correctChestPlacement(targetState, result))) {
285+
contextCache = context;
286+
return context;
287+
}
288288
}
289289
}
290290
}

v1_21/src/main/java/me/aleksilassila/litematica/printer/v1_21/guides/placement/PlacementGuide.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22

33
import me.aleksilassila.litematica.printer.v1_21.LitematicaMixinMod;
44
import me.aleksilassila.litematica.printer.v1_21.actions.*;
5+
import me.aleksilassila.litematica.printer.v1_21.config.PrinterConfig;
56
import me.aleksilassila.litematica.printer.v1_21.implementation.PrinterPlacementContext;
67
import me.aleksilassila.litematica.printer.v1_21.SchematicBlockState;
78
import me.aleksilassila.litematica.printer.v1_21.guides.Guide;
9+
import me.aleksilassila.litematica.printer.v1_21.implementation.actions.AirPlaceAction;
810
import me.aleksilassila.litematica.printer.v1_21.implementation.actions.InteractActionImpl;
911
import net.minecraft.block.*;
1012
import net.minecraft.client.MinecraftClient;
@@ -109,9 +111,13 @@ public boolean isInAir(BlockPos pos){
109111

110112
if (ctx.isAirPlace) {
111113
actionChain.addAction(new PrepareAction(ctx));
112-
actionChain.addAction(new InteractActionImpl(ctx));
114+
actionChain.addAction(new AirPlaceAction(ctx));
113115
actions.add(actionChain);
114116
return actions;
117+
} else {
118+
if (PrinterConfig.PRINTER_AIRPLACE.getBooleanValue() && PrinterConfig.PRINTER_AIRPLACE_ONLY.getBooleanValue()) {
119+
return actions;
120+
}
115121
}
116122

117123
actionChain.addAction(new PrepareLook(ctx));
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package me.aleksilassila.litematica.printer.v1_21.implementation.actions;
2+
3+
import me.aleksilassila.litematica.printer.v1_21.actions.InteractAction;
4+
import me.aleksilassila.litematica.printer.v1_21.config.PrinterConfig;
5+
import me.aleksilassila.litematica.printer.v1_21.implementation.PrinterPlacementContext;
6+
import net.minecraft.client.MinecraftClient;
7+
import net.minecraft.client.network.ClientPlayNetworkHandler;
8+
import net.minecraft.client.network.ClientPlayerEntity;
9+
import net.minecraft.client.network.ClientPlayerInteractionManager;
10+
import net.minecraft.network.packet.c2s.play.HandSwingC2SPacket;
11+
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket;
12+
import net.minecraft.util.ActionResult;
13+
import net.minecraft.util.Hand;
14+
import net.minecraft.util.hit.BlockHitResult;
15+
import net.minecraft.util.math.BlockPos;
16+
import net.minecraft.util.math.Direction;
17+
import net.minecraft.util.math.Vec3d;
18+
19+
public class AirPlaceAction extends InteractAction {
20+
private final MinecraftClient mc = MinecraftClient.getInstance();
21+
public AirPlaceAction(PrinterPlacementContext context) {
22+
super(context);
23+
}
24+
25+
@Override
26+
protected ActionResult interact(MinecraftClient client, ClientPlayerEntity player, Hand hand, BlockHitResult hitResult) {
27+
if (!mc.world.getBlockState(hitResult.getBlockPos().offset(hitResult.getSide())).isAir()) {
28+
if (PrinterConfig.PRINTER_DEBUG_LOG.getBooleanValue()) System.out.println("InteractActionImpl.interact: block is not air");
29+
return ActionResult.FAIL;
30+
}
31+
if (PrinterConfig.PRINTER_DEBUG_LOG.getBooleanValue()) System.out.println("InteractActionImpl.interact: attempting to air place block");
32+
airPlace(hitResult.getBlockPos().offset(hitResult.getSide()));
33+
return ActionResult.PASS;
34+
}
35+
36+
private void airPlace(BlockPos pos) {
37+
ClientPlayNetworkHandler connection = mc.getNetworkHandler();
38+
ClientPlayerInteractionManager interactionManager = mc.interactionManager;
39+
if (mc.player == null || connection == null || interactionManager == null) return;
40+
connection.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.UP));
41+
42+
Hand hand = Hand.OFF_HAND;
43+
44+
BlockHitResult hit = new BlockHitResult(Vec3d.ofCenter(pos), Direction.UP, pos, true);
45+
interactionManager.interactBlock(mc.player, hand, hit);
46+
mc.player.swingHand(Hand.MAIN_HAND, false);
47+
connection.sendPacket(new HandSwingC2SPacket(hand));
48+
connection.sendPacket(new PlayerActionC2SPacket(PlayerActionC2SPacket.Action.SWAP_ITEM_WITH_OFFHAND, BlockPos.ORIGIN, Direction.UP));
49+
}
50+
}

v1_21/src/main/java/me/aleksilassila/litematica/printer/v1_21/implementation/actions/InteractActionImpl.java

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,9 @@
66
import me.aleksilassila.litematica.printer.v1_21.implementation.PrinterPlacementContext;
77
import net.minecraft.client.MinecraftClient;
88
import net.minecraft.client.network.ClientPlayerEntity;
9-
import net.minecraft.item.ItemStack;
10-
import net.minecraft.network.packet.c2s.play.ClickSlotC2SPacket;
11-
import net.minecraft.network.packet.c2s.play.PlayerInteractBlockC2SPacket;
12-
import net.minecraft.network.packet.c2s.play.UpdateSelectedSlotC2SPacket;
13-
import net.minecraft.screen.slot.SlotActionType;
149
import net.minecraft.util.ActionResult;
1510
import net.minecraft.util.Hand;
1611
import net.minecraft.util.hit.BlockHitResult;
17-
import net.minecraft.util.math.BlockPos;
18-
import net.minecraft.util.math.Direction;
19-
import net.minecraft.util.math.Vec3d;
2012

2113
public class InteractActionImpl extends InteractAction {
2214
public InteractActionImpl(PrinterPlacementContext context) {
@@ -25,55 +17,11 @@ public InteractActionImpl(PrinterPlacementContext context) {
2517
private final MinecraftClient mc = MinecraftClient.getInstance();
2618
@Override
2719
protected ActionResult interact(MinecraftClient client, ClientPlayerEntity player, Hand hand, BlockHitResult hitResult) {
28-
if(context.isAirPlace) {
29-
if (PrinterConfig.PRINTER_DEBUG_LOG.getBooleanValue()) System.out.println("InteractActionImpl.interact: attempting to air place block");
30-
airPlace(hitResult.getBlockPos().offset(hitResult.getSide()));
31-
return ActionResult.PASS;
32-
}
33-
3420
ActionResult result = client.interactionManager.interactBlock(player, hand, hitResult);
3521
if (!result.isAccepted()) {
3622
if (PrinterConfig.PRINTER_DEBUG_LOG.getBooleanValue()) System.out.println("Failed to interact with block got " + result);
3723
}
38-
// client.interactionManager.interactItem(player, hand);
39-
// client.getNetworkHandler().sendPacket(new HandSwingC2SPacket(Hand.MAIN_HAND));
24+
mc.player.swingHand(Hand.MAIN_HAND, false);
4025
return result;
4126
}
42-
43-
public boolean isInAir(BlockPos pos){
44-
if(mc.world == null ) return false;
45-
for(Direction dir : Direction.values()){
46-
if(!mc.world.getBlockState(pos.offset(dir)).isAir()){
47-
return false;
48-
}
49-
}
50-
return true;
51-
}
52-
private void airPlace(BlockPos pos){
53-
swap();
54-
place(pos);
55-
swapBack();
56-
}
57-
58-
private void swap(){
59-
int ogSlot = mc.player.getInventory().getSlotWithStack(mc.player.getMainHandStack());
60-
mc.getNetworkHandler().sendPacket(new ClickSlotC2SPacket(0,0,ogSlot + 36,0, SlotActionType.SWAP,mc.player.getMainHandStack(),new Int2ObjectArrayMap<>()));
61-
mc.getNetworkHandler().sendPacket(new UpdateSelectedSlotC2SPacket(0));
62-
}
63-
64-
private void swapBack(){
65-
int ogSlot = mc.player.getInventory().getSlotWithStack(mc.player.getMainHandStack());
66-
mc.getNetworkHandler().sendPacket(new ClickSlotC2SPacket(0,0,ogSlot + 36,0,SlotActionType.SWAP,mc.player.getMainHandStack(),new Int2ObjectArrayMap<>()));
67-
mc.getNetworkHandler().sendPacket(new UpdateSelectedSlotC2SPacket(ogSlot));
68-
}
69-
70-
private void place(BlockPos pos){
71-
int slot = 36;
72-
ItemStack stack = mc.player.getMainHandStack();
73-
mc.getNetworkHandler().sendPacket(new ClickSlotC2SPacket(0,0,slot,0,SlotActionType.PICKUP,stack,new Int2ObjectArrayMap<>()));
74-
mc.getNetworkHandler().sendPacket(new PlayerInteractBlockC2SPacket(Hand.MAIN_HAND, new BlockHitResult(Vec3d.ofCenter(pos), Direction.DOWN, new BlockPos(pos), false), 0));
75-
mc.getNetworkHandler().sendPacket(new ClickSlotC2SPacket(0,0,slot,0,SlotActionType.PICKUP,stack,new Int2ObjectArrayMap<>()));
76-
mc.getNetworkHandler().sendPacket(new ClickSlotC2SPacket(0,0,slot,0,SlotActionType.PICKUP,stack,new Int2ObjectArrayMap<>()));
77-
}
78-
7927
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package me.aleksilassila.litematica.printer.v1_21.mixin;
2+
3+
import io.netty.channel.ChannelHandlerContext;
4+
import me.aleksilassila.litematica.printer.v1_21.LitematicaMixinMod;
5+
import me.aleksilassila.litematica.printer.v1_21.Printer;
6+
import me.aleksilassila.litematica.printer.v1_21.config.PrinterConfig;
7+
import net.minecraft.entity.player.PlayerInventory;
8+
import net.minecraft.network.ClientConnection;
9+
import net.minecraft.network.packet.Packet;
10+
import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket;
11+
import net.minecraft.screen.PlayerScreenHandler;
12+
import org.spongepowered.asm.mixin.Mixin;
13+
import org.spongepowered.asm.mixin.injection.At;
14+
import org.spongepowered.asm.mixin.injection.Inject;
15+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
16+
17+
@Mixin(ClientConnection.class)
18+
public class MixinClientConnection {
19+
@Inject(method = "channelRead0*", at = @At("HEAD"), cancellable = true)
20+
private void channelReadPre(ChannelHandlerContext channelHandlerContext, Packet<?> packet, CallbackInfo callback) {
21+
if (!LitematicaMixinMod.PRINT_MODE.getBooleanValue() && !LitematicaMixinMod.PRINT.getKeybind().isPressed()) {
22+
return;
23+
}
24+
if (!PrinterConfig.PRINTER_AIRPLACE.getBooleanValue() || !PrinterConfig.PRINTER_AIRPLACE_OFFHAND_SLOT_SUPPRESS.getBooleanValue()) {
25+
return;
26+
}
27+
if (Printer.inactivityCounter > 20) {
28+
return;
29+
}
30+
if (packet instanceof ScreenHandlerSlotUpdateS2CPacket packet1) {
31+
if (packet1.getSyncId() == -2 && packet1.getSlot() == PlayerInventory.OFF_HAND_SLOT) {
32+
callback.cancel();
33+
} else if (packet1.getSyncId() == 0 && PlayerScreenHandler.isInHotbar(packet1.getSyncId())) {
34+
if (packet1.getSlot() == PlayerScreenHandler.OFFHAND_ID) {
35+
callback.cancel();
36+
}
37+
}
38+
}
39+
}
40+
}

v1_21/src/main/resources/litematica-printer.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"package": "me.aleksilassila.litematica.printer.v1_21.mixin",
55
"compatibilityLevel": "JAVA_16",
66
"mixins": [
7+
"MixinClientConnection"
78
],
89
"client": [
910
"AxeItemAccessor",

0 commit comments

Comments
 (0)