Skip to content

Commit a58e10d

Browse files
Merge pull request #31 from Enzo1990-ui/1.21
Fix: Updated Clipboard Interaction for Latest Create (DataComponents & API Migration)
2 parents 480d2be + 822537f commit a58e10d

2 files changed

Lines changed: 96 additions & 79 deletions

File tree

.changeset/nasty-lions-collect.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"CreateColonies": patch
3+
---
4+
5+
fix: Crash of Create clipboard with the Minecolonies builder's hut (fixes #30)

src/main/java/nl/motionlesstrain/createcolonies/hooks/InteractionHook.java

Lines changed: 91 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.minecolonies.api.colony.buildings.IBuilding;
44
import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding;
5+
import com.simibubi.create.AllDataComponents;
6+
import com.simibubi.create.content.equipment.clipboard.ClipboardContent;
57
import com.simibubi.create.content.equipment.clipboard.ClipboardEntry;
68
import com.simibubi.create.content.equipment.clipboard.ClipboardOverrides;
79
import net.minecraft.ChatFormatting;
@@ -11,106 +13,116 @@
1113
import net.minecraft.network.chat.HoverEvent;
1214
import net.minecraft.network.chat.MutableComponent;
1315
import net.minecraft.network.chat.Style;
14-
import net.minecraft.util.Unit;
1516
import net.minecraft.world.InteractionResult;
1617
import net.minecraft.world.entity.player.Player;
1718
import net.minecraft.world.item.ItemStack;
1819
import net.minecraft.world.level.Level;
1920
import net.minecraft.world.level.block.entity.BlockEntity;
2021
import net.minecraft.world.level.block.state.BlockState;
21-
import net.neoforged.bus.api.SubscribeEvent;
2222
import net.neoforged.neoforge.common.util.FakePlayer;
2323
import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent;
24+
import net.neoforged.bus.api.SubscribeEvent;
2425
import nl.motionlesstrain.createcolonies.compatibility.Minecolonies;
25-
2626
import java.util.ArrayList;
2727
import java.util.List;
28+
import java.util.Optional;
2829
import java.util.TreeMap;
2930

3031
import static com.minecolonies.core.colony.buildings.modules.BuildingModules.BUILDING_RESOURCES;
31-
import static nl.motionlesstrain.createcolonies.resources.CreateResources.DataComponentTypes.clipboardPages;
32-
import static nl.motionlesstrain.createcolonies.resources.CreateResources.DataComponentTypes.clipboardReadOnly;
3332
import static nl.motionlesstrain.createcolonies.resources.CreateResources.Items.clipboard;
3433
import static nl.motionlesstrain.createcolonies.resources.MinecoloniesResources.Blocks.blockHutBuilder;
3534

3635
public class InteractionHook {
3736

38-
@SubscribeEvent
39-
public static void onPlayerRightClick(PlayerInteractEvent.RightClickBlock evt) {
40-
final Player player = evt.getEntity();
41-
if (!player.isShiftKeyDown()) return;
42-
43-
final Level world = evt.getLevel();
44-
final BlockPos blockPosClicked = evt.getHitVec().getBlockPos();
45-
final BlockState blockStateClicked = world.getBlockState(blockPosClicked);
46-
47-
final ItemStack heldItem = evt.getItemStack();
48-
49-
if (blockHutBuilder.isBound() && blockStateClicked.is(blockHutBuilder) && clipboard.isBound() && heldItem.is(clipboard)) {
50-
evt.setCanceled(true);
51-
evt.setCancellationResult(InteractionResult.SUCCESS);
52-
if (evt.getSide().isClient()) return;
53-
54-
if (player instanceof FakePlayer) return;
55-
56-
Minecolonies.runIfInstalled(() -> () -> {
57-
final BlockEntity blockEntity = world.getBlockEntity(blockPosClicked);
58-
if (blockEntity instanceof AbstractTileEntityColonyBuilding buildingEntity) {
59-
final IBuilding building = buildingEntity.getBuilding();
60-
final var resourcesModule = building.getModule(BUILDING_RESOURCES);
61-
if (resourcesModule != null) {
62-
final var allResources = resourcesModule.getNeededResources();
63-
final TreeMap<String, NeededItem> neededResources = new TreeMap<>();
64-
allResources.values().forEach(resource -> {
65-
final int entireAmount = resource.getAmount(),
66-
availableAmount = resource.getAvailable(),
67-
deliveringAmount = resource.getAmountInDelivery(),
68-
neededAmount = entireAmount - availableAmount - deliveringAmount;
69-
final ItemStack itemStack = resource.getItemStack();
70-
if (neededAmount > 0) {
71-
neededResources.put(itemStack.getItem().getName(itemStack).getString(),
72-
new NeededItem(itemStack, neededAmount, entireAmount));
73-
}
37+
@SubscribeEvent
38+
public static void onPlayerRightClick(PlayerInteractEvent.RightClickBlock evt) {
39+
final Player player = evt.getEntity();
40+
if (!player.isShiftKeyDown()) return;
41+
42+
final Level world = evt.getLevel();
43+
final BlockPos blockPosClicked = evt.getHitVec().getBlockPos();
44+
final BlockState blockStateClicked = world.getBlockState(blockPosClicked);
45+
final ItemStack heldItem = evt.getItemStack();
46+
47+
if (blockHutBuilder.isPresent() && blockStateClicked.is(blockHutBuilder.get()) && clipboard != null && heldItem.is(clipboard)) {
48+
evt.setCanceled(true);
49+
evt.setCancellationResult(InteractionResult.SUCCESS);
50+
51+
if (evt.getSide().isClient()) return;
52+
53+
if (player instanceof FakePlayer) return;
54+
55+
Minecolonies.runIfInstalled(() -> () -> {
56+
final BlockEntity blockEntity = world.getBlockEntity(blockPosClicked);
57+
if (blockEntity instanceof AbstractTileEntityColonyBuilding buildingEntity) {
58+
final IBuilding building = buildingEntity.getBuilding();
59+
final var resourcesModule = building.getModule(BUILDING_RESOURCES);
60+
if (resourcesModule != null) {
61+
final var allResources = resourcesModule.getNeededResources();
62+
final TreeMap<String, NeededItem> neededResources = new TreeMap<>();
63+
64+
allResources.values().forEach(resource -> {
65+
final int entireAmount = resource.getAmount(),
66+
availableAmount = resource.getAvailable(),
67+
deliveringAmount = resource.getAmountInDelivery(),
68+
neededAmount = entireAmount - availableAmount - deliveringAmount;
69+
final ItemStack itemStack = resource.getItemStack();
70+
if (neededAmount > 0) {
71+
neededResources.put(itemStack.getItem().getName(itemStack).getString(),
72+
new NeededItem(itemStack, neededAmount, entireAmount));
73+
}
74+
});
75+
76+
List<List<ClipboardEntry>> pages = new ArrayList<>();
77+
List<ClipboardEntry> currentEntries = new ArrayList<>();
78+
int i = 0;
79+
80+
for (final var neededItem : neededResources.values()) {
81+
final MutableComponent text = Component.translatable(neededItem.item.getDescriptionId()).setStyle(
82+
Style.EMPTY.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(neededItem.item)))
83+
).append(
84+
Component.literal("\n x" + neededItem.count).withStyle(ChatFormatting.BLACK)
85+
).append(
86+
Component.literal(" | " + neededItem.count / 64 + "▤ +" + neededItem.count % 64).withStyle(ChatFormatting.GRAY)
87+
);
88+
89+
ClipboardEntry entry = new ClipboardEntry(neededItem.count == 0, text);
90+
entry.displayItem(neededItem.item, neededItem.count);
91+
currentEntries.add(entry);
92+
93+
if (++i == 7) {
94+
currentEntries.add(new ClipboardEntry(false, Component.literal(">>>").withStyle(ChatFormatting.DARK_GRAY)));
95+
pages.add(new ArrayList<>(currentEntries));
96+
currentEntries.clear();
97+
i = 0;
98+
}
99+
}
100+
101+
if (!currentEntries.isEmpty()) {
102+
pages.add(new ArrayList<>(currentEntries));
103+
}
104+
105+
ClipboardContent content = new ClipboardContent(
106+
ClipboardOverrides.ClipboardType.WRITTEN,
107+
pages,
108+
true,
109+
0,
110+
Optional.empty()
111+
);
112+
113+
heldItem.set(AllDataComponents.CLIPBOARD_CONTENT, content);
114+
115+
heldItem.set(DataComponents.CUSTOM_NAME,
116+
Component.translatable("create.materialChecklist").setStyle(Style.EMPTY.withItalic(Boolean.FALSE)));
117+
118+
final Component message = Component.translatable("nl.motionlesstrain.createcolonies.clipboard.registered",
119+
Component.translatable(building.getBuildingDisplayName())).setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY));
120+
player.displayClientMessage(message, false);
121+
}
122+
}
74123
});
75-
// Inspired by MaterialChecklist, which is part of the schematicannon code to write resources into a clipboard
76-
final List<List<ClipboardEntry>> pages = new ArrayList<>();
77-
List<ClipboardEntry> entries = new ArrayList<>();
78-
int i = 0;
79-
for (final var neededItem : neededResources.values()) {
80-
final MutableComponent text = Component.translatable(neededItem.item.getDescriptionId()).setStyle(
81-
Style.EMPTY.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(neededItem.item)))
82-
).append(
83-
Component.literal("\n x" + neededItem.count).withStyle(ChatFormatting.BLACK)
84-
).append(
85-
Component.literal(" | " + neededItem.count / 64 + "▤ +" + neededItem.count % 64).withStyle(ChatFormatting.GRAY)
86-
);
87-
entries.add(
88-
new ClipboardEntry(neededItem.count == 0, text).displayItem(neededItem.item, neededItem.count));
89-
90-
if (++i == 7) {
91-
entries.add(
92-
new ClipboardEntry(false, Component.literal(">>>").withStyle(ChatFormatting.DARK_GRAY)));
93-
pages.add(entries);
94-
entries = new ArrayList<>();
95-
i = 0;
96-
}
97-
}
98-
if (i > 0) {
99-
pages.add(entries);
100-
}
101-
ClipboardOverrides.switchTo(ClipboardOverrides.ClipboardType.WRITTEN, heldItem);
102-
heldItem.set(clipboardPages, pages);
103-
heldItem.set(DataComponents.CUSTOM_NAME, Component.translatable("create.materialChecklist").setStyle(Style.EMPTY.withItalic(Boolean.FALSE)));
104-
heldItem.set(clipboardReadOnly, Unit.INSTANCE);
105-
106-
final Component message = Component.translatable("nl.motionlesstrain.createcolonies.clipboard.registered",
107-
Component.translatable(building.getBuildingDisplayName())).setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY));
108-
player.displayClientMessage(message, false);
109-
}
110124
}
111-
});
112125
}
113-
}
114126

115-
private record NeededItem(ItemStack item, int count, int totalCount) {}
127+
private record NeededItem(ItemStack item, int count, int totalCount) {}
116128
}

0 commit comments

Comments
 (0)