Skip to content

Commit 85d0a14

Browse files
Copy tool to Pattern (#7)
1 parent e899727 commit 85d0a14

5 files changed

Lines changed: 221 additions & 1 deletion

File tree

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.ref.aea.mixin.buildinggadgets2;
2+
3+
import com.direwolf20.buildinggadgets2.common.network.packets.PacketUpdateTemplateManager;
4+
import org.spongepowered.asm.mixin.Mixin;
5+
import org.spongepowered.asm.mixin.gen.Accessor;
6+
7+
@Mixin(value = PacketUpdateTemplateManager.class, remap = false)
8+
public interface PacketUpdateTemplateManagerAccessor {
9+
@Accessor("mode")
10+
int getMode();
11+
12+
@Accessor("templateName")
13+
String getTemplateName();
14+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package com.ref.aea.mixin.buildinggadgets2;
2+
3+
import appeng.core.definitions.AEItems;
4+
import com.direwolf20.buildinggadgets2.common.containers.TemplateManagerContainer;
5+
import com.direwolf20.buildinggadgets2.common.network.packets.PacketUpdateTemplateManager;
6+
import com.direwolf20.buildinggadgets2.common.worlddata.BG2Data;
7+
import com.direwolf20.buildinggadgets2.util.GadgetNBT;
8+
import com.direwolf20.buildinggadgets2.util.MiscHelpers;
9+
import com.direwolf20.buildinggadgets2.util.datatypes.StatePos;
10+
import com.ref.aea.util.EncodedPatternUtil;
11+
import java.util.ArrayList;
12+
import java.util.Objects;
13+
import java.util.UUID;
14+
import java.util.function.Supplier;
15+
import net.minecraft.core.Holder;
16+
import net.minecraft.server.level.ServerPlayer;
17+
import net.minecraft.sounds.SoundEvent;
18+
import net.minecraft.sounds.SoundEvents;
19+
import net.minecraft.world.inventory.AbstractContainerMenu;
20+
import net.minecraft.world.item.ItemStack;
21+
import net.minecraftforge.network.NetworkEvent;
22+
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.Unique;
24+
import org.spongepowered.asm.mixin.injection.At;
25+
import org.spongepowered.asm.mixin.injection.Inject;
26+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
27+
28+
@Mixin(value = PacketUpdateTemplateManager.class, remap = false)
29+
public abstract class PacketUpdateTemplateManagerMixin {
30+
31+
@Inject(method = "handle", at = @At("HEAD"), cancellable = true)
32+
private static void onHandle(
33+
PacketUpdateTemplateManager message,
34+
Supplier<NetworkEvent.Context> context,
35+
CallbackInfo ci) {
36+
NetworkEvent.Context ctx = context.get();
37+
ServerPlayer sender = ctx.getSender();
38+
if (sender == null) return;
39+
40+
PacketUpdateTemplateManagerAccessor accessor = (PacketUpdateTemplateManagerAccessor) message;
41+
if (accessor.getMode() != 0) return;
42+
43+
ci.cancel();
44+
45+
ctx.enqueueWork(
46+
() -> {
47+
AbstractContainerMenu container = sender.containerMenu;
48+
if (!(container instanceof TemplateManagerContainer menu)) return;
49+
50+
ItemStack templateStack = menu.getSlot(1).getItem();
51+
if (!templateStack.is(AEItems.BLANK_PATTERN.asItem())
52+
&& !templateStack.is(AEItems.PROCESSING_PATTERN.asItem())) {
53+
return;
54+
}
55+
56+
ItemStack gadgetStack = menu.getSlot(0).getItem();
57+
UUID sourceUUID = GadgetNBT.getUUID(gadgetStack);
58+
59+
BG2Data bg2Data =
60+
BG2Data.get(Objects.requireNonNull(sender.level().getServer()).overworld());
61+
ArrayList<StatePos> buildList = bg2Data.getCopyPasteList(sourceUUID, false);
62+
63+
if (buildList == null || buildList.isEmpty()) {
64+
AEA$playFailSound(sender);
65+
return;
66+
}
67+
68+
ItemStack encodedPattern =
69+
EncodedPatternUtil.fromBuildList(
70+
sender.serverLevel(), sender, buildList, accessor.getTemplateName());
71+
72+
if (!encodedPattern.isEmpty()) {
73+
menu.setItem(1, menu.getStateId(), encodedPattern);
74+
AEA$playSuccessSound(sender);
75+
}
76+
});
77+
}
78+
79+
@Unique
80+
private static void AEA$playFailSound(ServerPlayer player) {
81+
MiscHelpers.playSound(
82+
player,
83+
Holder.direct(
84+
SoundEvent.createVariableRangeEvent(
85+
SoundEvents.WAXED_SIGN_INTERACT_FAIL.getLocation())));
86+
}
87+
88+
@Unique
89+
private static void AEA$playSuccessSound(ServerPlayer player) {
90+
MiscHelpers.playSound(
91+
player,
92+
Holder.direct(
93+
SoundEvent.createVariableRangeEvent(SoundEvents.ENCHANTMENT_TABLE_USE.getLocation())));
94+
}
95+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.ref.aea.mixin.buildinggadgets2;
2+
3+
import appeng.core.definitions.AEItems;
4+
import com.direwolf20.buildinggadgets2.common.containers.customhandler.TemplateManagerHandler;
5+
import javax.annotation.Nonnull;
6+
import net.minecraft.world.item.ItemStack;
7+
import org.spongepowered.asm.mixin.Mixin;
8+
import org.spongepowered.asm.mixin.injection.At;
9+
import org.spongepowered.asm.mixin.injection.Inject;
10+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
11+
12+
@Mixin(value = TemplateManagerHandler.class, remap = false)
13+
public abstract class TemplateManagerHandlerMixin {
14+
15+
@Inject(
16+
method = "isItemValid(ILnet/minecraft/world/item/ItemStack;)Z",
17+
at = @At("RETURN"),
18+
cancellable = true)
19+
private void addAE2PatternsValidation(
20+
int slot, @Nonnull ItemStack stack, CallbackInfoReturnable<Boolean> cir) {
21+
if (cir.getReturnValue()) {
22+
return;
23+
}
24+
if (slot == 1
25+
&& (stack.is(AEItems.PROCESSING_PATTERN.asItem())
26+
|| stack.is(AEItems.BLANK_PATTERN.asItem()))) {
27+
cir.setReturnValue(true);
28+
}
29+
}
30+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package com.ref.aea.util;
2+
3+
import appeng.api.stacks.AEFluidKey;
4+
import appeng.api.stacks.AEItemKey;
5+
import appeng.api.stacks.AEKey;
6+
import appeng.api.stacks.GenericStack;
7+
import appeng.core.definitions.AEItems;
8+
import com.direwolf20.buildinggadgets2.setup.Registration;
9+
import com.direwolf20.buildinggadgets2.util.GadgetUtils;
10+
import com.direwolf20.buildinggadgets2.util.datatypes.StatePos;
11+
import java.util.*;
12+
import net.minecraft.core.BlockPos;
13+
import net.minecraft.network.chat.Component;
14+
import net.minecraft.server.level.ServerLevel;
15+
import net.minecraft.server.level.ServerPlayer;
16+
import net.minecraft.world.item.ItemStack;
17+
import net.minecraft.world.level.block.state.BlockState;
18+
import org.jetbrains.annotations.NotNull;
19+
20+
public class EncodedPatternUtil {
21+
public static ItemStack fromBuildList(
22+
ServerLevel level, ServerPlayer player, ArrayList<StatePos> buildList, String templateName) {
23+
if (buildList == null || buildList.isEmpty()) return ItemStack.EMPTY;
24+
Map<AEKey, Long> counts = getAeKeyLongMap(level, player, buildList);
25+
26+
if (counts.isEmpty()) return ItemStack.EMPTY;
27+
28+
List<GenericStack> inputs =
29+
counts.entrySet().stream()
30+
.map(e -> new GenericStack(e.getKey(), e.getValue()))
31+
.sorted((a, b) -> Long.compare(b.amount(), a.amount()))
32+
.limit(81)
33+
.toList();
34+
35+
ItemStack barrierStack = new ItemStack(Registration.Template.get());
36+
if (templateName != null && !templateName.isBlank()) {
37+
barrierStack.setHoverName(Component.literal(templateName));
38+
}
39+
40+
AEKey outputKey = AEItemKey.of(barrierStack);
41+
if (outputKey == null) return ItemStack.EMPTY;
42+
43+
GenericStack[] outputs = new GenericStack[] {new GenericStack(outputKey, 1)};
44+
45+
return AEItems.PROCESSING_PATTERN.asItem().encode(inputs.toArray(new GenericStack[0]), outputs);
46+
}
47+
48+
private static @NotNull Map<AEKey, Long> getAeKeyLongMap(
49+
ServerLevel level, ServerPlayer player, ArrayList<StatePos> buildList) {
50+
Map<AEKey, Long> counts = new HashMap<>();
51+
Map<BlockState, Map<AEKey, Long>> cacheMap = new HashMap<>();
52+
for (StatePos sp : buildList) {
53+
if (sp.state.isAir()) continue;
54+
Map<AEKey, Long> requirementsForState =
55+
cacheMap.computeIfAbsent(
56+
sp.state,
57+
state -> {
58+
Map<AEKey, Long> singleStateReqs = new HashMap<>();
59+
if (!state.getFluidState().isEmpty() && state.getFluidState().isSource()) {
60+
AEKey key = AEFluidKey.of(state.getFluidState().getType());
61+
singleStateReqs.put(key, 1000L);
62+
} else {
63+
List<ItemStack> drops =
64+
GadgetUtils.getDropsForBlockState(level, BlockPos.ZERO, state, player);
65+
for (ItemStack req : drops) {
66+
AEKey key = AEItemKey.of(req);
67+
if (key != null) {
68+
singleStateReqs.merge(key, (long) req.getCount(), Long::sum);
69+
}
70+
}
71+
}
72+
return singleStateReqs;
73+
});
74+
requirementsForState.forEach((key, amount) -> counts.merge(key, amount, Long::sum));
75+
}
76+
return counts;
77+
}
78+
}

src/main/resources/aea.mixins.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
"ae.cycle.PatternEncodingTermMenuMixin",
1818
"ae.item.EncodedPatternItemCommonMixin",
1919
"ae.item.QuartzCuttingKnifeItemMixin",
20-
"ae.recipe.InscriberRecipeCategoryMixin"
20+
"ae.recipe.InscriberRecipeCategoryMixin",
21+
"buildinggadgets2.PacketUpdateTemplateManagerAccessor",
22+
"buildinggadgets2.PacketUpdateTemplateManagerMixin",
23+
"buildinggadgets2.TemplateManagerHandlerMixin"
2124
],
2225
"client": [
2326
"ae.AEBaseScreenMixin",

0 commit comments

Comments
 (0)