Skip to content

Commit 742561f

Browse files
committed
Clipboard Refactoring
- Backwards compat - Remove ClipboardBlockEntity#dataContainer - Fix dropped clipboards not having components
1 parent ad94d8d commit 742561f

File tree

8 files changed

+126
-49
lines changed

8 files changed

+126
-49
lines changed

src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlock.java

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
import net.minecraft.client.Minecraft;
1818
import net.minecraft.core.BlockPos;
1919
import net.minecraft.core.Direction;
20+
import net.minecraft.core.component.DataComponentMap;
2021
import net.minecraft.world.InteractionResult;
22+
import net.minecraft.world.entity.player.Inventory;
2123
import net.minecraft.world.entity.player.Player;
2224
import net.minecraft.world.item.ItemStack;
2325
import net.minecraft.world.item.context.BlockPlaceContext;
@@ -28,6 +30,7 @@
2830
import net.minecraft.world.level.block.Block;
2931
import net.minecraft.world.level.block.FaceAttachedHorizontalDirectionalBlock;
3032
import net.minecraft.world.level.block.ShulkerBoxBlock;
33+
import net.minecraft.world.level.block.entity.BlockEntity;
3134
import net.minecraft.world.level.block.entity.BlockEntityType;
3235
import net.minecraft.world.level.block.state.BlockState;
3336
import net.minecraft.world.level.block.state.StateDefinition.Builder;
@@ -37,9 +40,9 @@
3740
import net.minecraft.world.level.storage.loot.LootParams;
3841
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
3942
import net.minecraft.world.phys.BlockHitResult;
40-
import net.minecraft.world.phys.HitResult;
4143
import net.minecraft.world.phys.shapes.CollisionContext;
4244
import net.minecraft.world.phys.shapes.VoxelShape;
45+
4346
import net.neoforged.api.distmarker.Dist;
4447
import net.neoforged.api.distmarker.OnlyIn;
4548
import net.neoforged.neoforge.common.util.FakePlayer;
@@ -96,15 +99,15 @@ protected InteractionResult useWithoutItem(BlockState state, Level level, BlockP
9699

97100
return onBlockEntityUse(level, pos, cbe -> {
98101
if (level.isClientSide())
99-
CatnipServices.PLATFORM.executeOnClientOnly(() -> () -> openScreen(player, cbe.dataContainer, pos));
102+
CatnipServices.PLATFORM.executeOnClientOnly(() -> () -> openScreen(player, cbe.components(), pos));
100103
return InteractionResult.SUCCESS;
101104
});
102105
}
103106

104107
@OnlyIn(Dist.CLIENT)
105-
private void openScreen(Player player, ItemStack stack, BlockPos pos) {
108+
private void openScreen(Player player, DataComponentMap components, BlockPos pos) {
106109
if (Minecraft.getInstance().player == player)
107-
ScreenOpener.open(new ClipboardScreen(player.getInventory().selected, stack, pos));
110+
ScreenOpener.open(new ClipboardScreen(player.getInventory().selected, components, pos));
108111
}
109112

110113
@Override
@@ -119,36 +122,49 @@ private void breakAndCollect(BlockState pState, Level pLevel, BlockPos pPos, Pla
119122
return;
120123
ItemStack cloneItemStack = getCloneItemStack(pLevel, pPos, pState);
121124
pLevel.destroyBlock(pPos, false);
122-
if (pLevel.getBlockState(pPos) != pState)
123-
pPlayer.getInventory()
124-
.placeItemBackInInventory(cloneItemStack);
125+
if (pLevel.getBlockState(pPos) != pState) {
126+
Inventory inv = pPlayer.getInventory();
127+
ItemStack selected = inv.getSelected();
128+
if (selected.isEmpty()) {
129+
inv.setItem(inv.selected, cloneItemStack);
130+
} else {
131+
inv.placeItemBackInInventory(cloneItemStack);
132+
}
133+
}
125134
}
126-
135+
127136
@Override
128137
public ItemStack getCloneItemStack(LevelReader level, BlockPos pos, BlockState state) {
129-
if (level.getBlockEntity(pos) instanceof ClipboardBlockEntity cbe)
130-
return cbe.dataContainer;
131-
return new ItemStack(this);
138+
return applyComponentsToDropStack(new ItemStack(this), level.getBlockEntity(pos));
132139
}
133140

134141
@Override
135-
public BlockState playerWillDestroy(Level pLevel, BlockPos pPos, BlockState pState, Player pPlayer) {
136-
if (!(pLevel.getBlockEntity(pPos) instanceof ClipboardBlockEntity cbe))
137-
return pState;
138-
if (pLevel.isClientSide || pPlayer.isCreative())
139-
return pState;
140-
Block.popResource(pLevel, pPos, cbe.dataContainer.copy());
142+
public BlockState playerWillDestroy(Level level, BlockPos pos, BlockState state, Player player) {
143+
if (!(level.getBlockEntity(pos) instanceof ClipboardBlockEntity cbe))
144+
return state;
145+
if (level.isClientSide || player.isCreative())
146+
return state;
147+
Block.popResource(level, pos, applyComponentsToDropStack(new ItemStack(this), cbe));
141148

142-
return pState;
149+
return state;
143150
}
144151

145152
@Override
146-
@SuppressWarnings("deprecation")
147153
public List<ItemStack> getDrops(BlockState pState, LootParams.Builder pBuilder) {
148154
if (!(pBuilder.getOptionalParameter(LootContextParams.BLOCK_ENTITY) instanceof ClipboardBlockEntity cbe))
149155
return super.getDrops(pState, pBuilder);
150-
pBuilder.withDynamicDrop(ShulkerBoxBlock.CONTENTS, p_56219_ -> p_56219_.accept(cbe.dataContainer.copy()));
151-
return ImmutableList.of(cbe.dataContainer.copy());
156+
ItemStack drop = applyComponentsToDropStack(new ItemStack(this), cbe);
157+
pBuilder.withDynamicDrop(ShulkerBoxBlock.CONTENTS, c -> c.accept(drop.copy()));
158+
return ImmutableList.of(drop);
159+
}
160+
161+
@SuppressWarnings("deprecation")
162+
private ItemStack applyComponentsToDropStack(ItemStack stack, BlockEntity blockEntity) {
163+
if (blockEntity instanceof ClipboardBlockEntity cbe) {
164+
stack.applyComponents(cbe.components());
165+
return stack;
166+
}
167+
return stack;
152168
}
153169

154170
@Override

src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockEntity.java

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.List;
44
import java.util.UUID;
55

6+
import com.mojang.datafixers.util.Pair;
67
import com.simibubi.create.AllBlocks;
78
import com.simibubi.create.AllDataComponents;
89
import com.simibubi.create.content.logistics.AddressEditBoxHelper;
@@ -13,24 +14,21 @@
1314
import net.minecraft.client.Minecraft;
1415
import net.minecraft.core.BlockPos;
1516
import net.minecraft.core.HolderLookup;
17+
import net.minecraft.core.component.DataComponentMap;
1618
import net.minecraft.nbt.CompoundTag;
19+
import net.minecraft.nbt.NbtOps;
1720
import net.minecraft.world.entity.player.Player;
18-
import net.minecraft.world.item.ItemStack;
1921
import net.minecraft.world.level.block.entity.BlockEntityType;
2022
import net.minecraft.world.level.block.state.BlockState;
2123

2224
import net.neoforged.api.distmarker.Dist;
2325
import net.neoforged.api.distmarker.OnlyIn;
2426

2527
public class ClipboardBlockEntity extends SmartBlockEntity {
26-
27-
@Deprecated(forRemoval = true)
28-
public ItemStack dataContainer;
2928
private UUID lastEdit;
3029

3130
public ClipboardBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
3231
super(type, pos, state);
33-
dataContainer = AllBlocks.CLIPBOARD.asStack();
3432
}
3533

3634
@Override
@@ -59,7 +57,7 @@ public void updateWrittenState() {
5957
if (level.isClientSide())
6058
return;
6159
boolean isWritten = blockState.getValue(ClipboardBlock.WRITTEN);
62-
boolean shouldBeWritten = !dataContainer.getComponentsPatch().isEmpty();
60+
boolean shouldBeWritten = components().has(AllDataComponents.CLIPBOARD_CONTENT);
6361
if (isWritten == shouldBeWritten)
6462
return;
6563
level.setBlockAndUpdate(worldPosition, blockState.setValue(ClipboardBlock.WRITTEN, shouldBeWritten));
@@ -71,20 +69,30 @@ public void addBehaviours(List<BlockEntityBehaviour> behaviours) {}
7169
@Override
7270
protected void write(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) {
7371
super.write(tag, registries, clientPacket);
74-
tag.put("Item", dataContainer.saveOptional(registries));
75-
if (clientPacket && lastEdit != null)
76-
tag.putUUID("LastEdit", lastEdit);
72+
73+
if (clientPacket) {
74+
DataComponentMap.CODEC.encodeStart(NbtOps.INSTANCE, components())
75+
.result()
76+
.ifPresent(encoded -> tag.put("components", encoded));
77+
78+
if (lastEdit != null)
79+
tag.putUUID("LastEdit", lastEdit);
80+
}
7781
}
7882

7983
@Override
8084
protected void read(CompoundTag tag, HolderLookup.Provider registries, boolean clientPacket) {
8185
super.read(tag, registries, clientPacket);
82-
dataContainer = ItemStack.parseOptional(registries, tag.getCompound("Item"));
83-
if (!AllBlocks.CLIPBOARD.isIn(dataContainer))
84-
dataContainer = AllBlocks.CLIPBOARD.asStack();
8586

86-
if (clientPacket)
87+
if (clientPacket) {
88+
if (tag.contains("components"))
89+
DataComponentMap.CODEC.decode(NbtOps.INSTANCE, tag.getCompound("components"))
90+
.result()
91+
.map(Pair::getFirst)
92+
.ifPresent(this::setComponents);
93+
8794
CatnipServices.PLATFORM.executeOnClientOnly(() -> () -> readClientSide(tag));
95+
}
8896
}
8997

9098
@OnlyIn(Dist.CLIENT)
@@ -105,4 +113,8 @@ private void advertiseToAddressHelper() {
105113
AddressEditBoxHelper.advertiseClipboard(this);
106114
}
107115

116+
@Override
117+
public void setComponents(DataComponentMap components) {
118+
super.setComponents(components);
119+
}
108120
}

src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardBlockItem.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import net.createmod.catnip.platform.CatnipServices;
1111
import net.minecraft.client.Minecraft;
1212
import net.minecraft.core.BlockPos;
13+
import net.minecraft.core.component.DataComponentMap;
1314
import net.minecraft.core.component.DataComponentType;
1415
import net.minecraft.world.InteractionHand;
1516
import net.minecraft.world.InteractionResult;
@@ -49,7 +50,6 @@ protected boolean updateCustomBlockEntityTag(BlockPos pPos, Level pLevel, Player
4950
return false;
5051
if (!(pLevel.getBlockEntity(pPos) instanceof ClipboardBlockEntity cbe))
5152
return false;
52-
cbe.dataContainer = pStack.copyWithCount(1);
5353
cbe.notifyUpdate();
5454
return true;
5555
}
@@ -63,17 +63,17 @@ public InteractionResultHolder<ItemStack> use(Level world, Player player, Intera
6363
player.getCooldowns()
6464
.addCooldown(heldItem.getItem(), 10);
6565
if (world.isClientSide)
66-
CatnipServices.PLATFORM.executeOnClientOnly(() -> () -> openScreen(player, heldItem));
66+
CatnipServices.PLATFORM.executeOnClientOnly(() -> () -> openScreen(player, heldItem.getComponents()));
6767
ClipboardContent content = heldItem.getOrDefault(AllDataComponents.CLIPBOARD_CONTENT, ClipboardContent.EMPTY);
6868
heldItem.set(AllDataComponents.CLIPBOARD_CONTENT, content.setType(ClipboardType.EDITING));
6969

7070
return InteractionResultHolder.success(heldItem);
7171
}
7272

7373
@OnlyIn(Dist.CLIENT)
74-
private void openScreen(Player player, ItemStack stack) {
74+
private void openScreen(Player player, DataComponentMap components) {
7575
if (Minecraft.getInstance().player == player)
76-
ScreenOpener.open(new ClipboardScreen(player.getInventory().selected, stack, null));
76+
ScreenOpener.open(new ClipboardScreen(player.getInventory().selected, components, null));
7777
}
7878

7979
public void registerModelOverrides() {

src/main/java/com/simibubi/create/content/equipment/clipboard/ClipboardScreen.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@
4444
import net.minecraft.client.renderer.Rect2i;
4545
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
4646
import net.minecraft.core.BlockPos;
47+
import net.minecraft.core.component.DataComponentMap;
4748
import net.minecraft.network.chat.Component;
4849
import net.minecraft.network.chat.MutableComponent;
4950
import net.minecraft.network.chat.Style;
5051
import net.minecraft.util.FormattedCharSequence;
5152
import net.minecraft.util.Mth;
5253
import net.minecraft.util.StringUtil;
53-
import net.minecraft.world.item.ItemStack;
5454

5555
import net.neoforged.api.distmarker.Dist;
5656
import net.neoforged.api.distmarker.OnlyIn;
@@ -82,10 +82,10 @@ public class ClipboardScreen extends AbstractSimiScreen {
8282

8383
private final int targetSlot;
8484

85-
public ClipboardScreen(int targetSlot, ItemStack item, @Nullable BlockPos pos) {
85+
public ClipboardScreen(int targetSlot, DataComponentMap components, @Nullable BlockPos pos) {
8686
this.targetSlot = targetSlot;
8787
this.targetedBlock = pos;
88-
reopenWith(item.getOrDefault(AllDataComponents.CLIPBOARD_CONTENT, ClipboardContent.EMPTY));
88+
reopenWith(components.getOrDefault(AllDataComponents.CLIPBOARD_CONTENT, ClipboardContent.EMPTY));
8989
}
9090

9191
public void reopenWith(ClipboardContent content) {

src/main/java/com/simibubi/create/content/logistics/AddressEditBoxHelper.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import net.minecraft.client.gui.components.EditBox;
1919
import net.minecraft.client.gui.screens.Screen;
2020
import net.minecraft.core.BlockPos;
21+
import net.minecraft.core.component.DataComponentMap;
2122
import net.minecraft.world.entity.player.Inventory;
2223
import net.minecraft.world.entity.player.Player;
2324
import net.minecraft.world.item.ItemStack;
@@ -49,21 +50,20 @@ public static DestinationSuggestions createSuggestions(Screen screen, EditBox pI
4950

5051
if (player == null)
5152
return destinationSuggestions;
52-
53+
5354
if (localAddress != null) {
5455
options.add(IntAttached.with(-1, localAddress));
5556
alreadyAdded.add(localAddress);
5657
}
5758

5859
for (int i = 0; i < Inventory.INVENTORY_SIZE; i++)
59-
appendAddresses(options, alreadyAdded, player.getInventory()
60-
.getItem(i));
60+
appendAddresses(options, alreadyAdded, player.getInventory().getItem(i));
6161

6262
for (WeakReference<ClipboardBlockEntity> wr : NEARBY_CLIPBOARDS.asMap()
6363
.values()) {
6464
ClipboardBlockEntity cbe = wr.get();
6565
if (cbe != null)
66-
appendAddresses(options, alreadyAdded, cbe.dataContainer);
66+
appendAddresses(options, alreadyAdded, cbe.components());
6767
}
6868

6969
return destinationSuggestions;
@@ -73,12 +73,16 @@ private static void appendAddresses(List<IntAttached<String>> options, Set<Strin
7373
if (item == null || !AllBlocks.CLIPBOARD.isIn(item))
7474
return;
7575

76-
List<List<ClipboardEntry>> pages = ClipboardEntry.readAll(item);
76+
appendAddresses(options, alreadyAdded, item.getComponents());
77+
}
78+
79+
private static void appendAddresses(List<IntAttached<String>> options, Set<String> alreadyAdded, DataComponentMap components) {
80+
List<List<ClipboardEntry>> pages = ClipboardEntry.readAll(components);
7781
pages.forEach(page -> page.forEach(entry -> {
7882
String string = entry.text.getString();
7983
if (entry.checked)
8084
return;
81-
if (!string.startsWith("#") || string.length() <= 1)
85+
if (!string.startsWith("#") || string.length() == 1)
8286
return;
8387
String address = string.substring(1);
8488
if (address.isBlank())

src/main/java/com/simibubi/create/foundation/blockEntity/SyncedBlockEntity.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
@MethodsReturnNonnullByDefault
2121
@ParametersAreNonnullByDefault
2222
public abstract class SyncedBlockEntity extends BlockEntity {
23-
2423
public SyncedBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
2524
super(type, pos, state);
2625
}
@@ -70,5 +69,4 @@ public void notifyUpdate() {
7069
public HolderGetter<Block> blockHolderGetter() {
7170
return level != null ? level.holderLookup(Registries.BLOCK) : BuiltInRegistries.BLOCK.asLookup();
7271
}
73-
7472
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package com.simibubi.create.foundation.mixin;
2+
3+
import java.util.function.BiFunction;
4+
5+
import org.spongepowered.asm.mixin.Mixin;
6+
import org.spongepowered.asm.mixin.Unique;
7+
import org.spongepowered.asm.mixin.injection.At;
8+
import org.spongepowered.asm.mixin.injection.Inject;
9+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
10+
11+
import com.simibubi.create.AllDataComponents;
12+
import com.simibubi.create.content.equipment.clipboard.ClipboardContent;
13+
14+
import net.minecraft.core.component.DataComponentType;
15+
import net.minecraft.core.component.PatchedDataComponentMap;
16+
import net.minecraft.world.item.ItemStack;
17+
import net.minecraft.world.level.ItemLike;
18+
19+
@Mixin(ItemStack.class)
20+
public class ItemStackMixin {
21+
@Inject(method = "<init>(Lnet/minecraft/world/level/ItemLike;ILnet/minecraft/core/component/PatchedDataComponentMap;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/item/Item;verifyComponentsAfterLoad(Lnet/minecraft/world/item/ItemStack;)V"))
22+
private void create$migrateOldClipboardComponents(ItemLike item, int count, PatchedDataComponentMap components, CallbackInfo ci) {
23+
ClipboardContent content = ClipboardContent.EMPTY;
24+
25+
content = create$migrateComponent(content, components, AllDataComponents.CLIPBOARD_PAGES, ClipboardContent::setPages);
26+
content = create$migrateComponent(content, components, AllDataComponents.CLIPBOARD_TYPE, ClipboardContent::setType);
27+
content = create$migrateComponent(content, components, AllDataComponents.CLIPBOARD_READ_ONLY, (c, v) -> c.setReadOnly(true));
28+
content = create$migrateComponent(content, components, AllDataComponents.CLIPBOARD_COPIED_VALUES, ClipboardContent::setCopiedValues);
29+
content = create$migrateComponent(content, components, AllDataComponents.CLIPBOARD_PREVIOUSLY_OPENED_PAGE, ClipboardContent::setPreviouslyOpenedPage);
30+
31+
if (content != ClipboardContent.EMPTY) {
32+
components.set(AllDataComponents.CLIPBOARD_CONTENT, content);
33+
}
34+
}
35+
36+
@Unique
37+
private static <T> ClipboardContent create$migrateComponent(ClipboardContent content, PatchedDataComponentMap components, DataComponentType<T> componentType, BiFunction<ClipboardContent, T, ClipboardContent> function) {
38+
T value = components.get(componentType);
39+
if (value != null) {
40+
components.remove(componentType);
41+
content = function.apply(content, value);
42+
}
43+
44+
return content;
45+
}
46+
}

src/main/resources/create.mixins.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"CustomItemUseEffectsMixin",
1414
"EnchantedCountIncreaseFunctionMixin",
1515
"EntityMixin",
16+
"ItemStackMixin",
1617
"LavaSwimmingMixin",
1718
"MapItemSavedDataMixin",
1819
"MobMixin",

0 commit comments

Comments
 (0)