From 8e03372bb3eaa0b88a553dd9236db17a967fa28b Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Thu, 11 May 2023 14:15:56 +0200 Subject: [PATCH] Hacking the printer - Fixed Smart Fluid Pipe not dropping filter when broken - Fixed Clipboard crashing game when removing the first entry of a page - Placards and Creative Crates will no longer hold on to special nbt content (except potion data, damage, enchants) of the contained item when imported via Schematicannon - Schematicannons can no longer print mobs - Fixed item frames not requiring an exact nbt match for printed contents --- src/generated/resources/.cache/cache | 4 +- .../resources/assets/create/lang/en_us.json | 2 +- .../java/com/simibubi/create/AllBlocks.java | 3 - .../fluids/pipes/SmartFluidPipeBlock.java | 3 +- .../clipboard/ClipboardScreen.java | 2 +- .../content/schematics/ItemRequirement.java | 44 +++++++------ .../ponder/content/RollerScenes.java | 2 +- .../foundation/utility/NBTProcessors.java | 61 +++++++++++++++++-- 8 files changed, 87 insertions(+), 34 deletions(-) diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 8b51b26dd..cd3a59bbf 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -582,7 +582,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json fcaad84ac4ebdb1e6d9301b77245ce855dbde503 assets/create/lang/en_ud.json -8c536f441c4515d44faf340cefb2c0247b49033a assets/create/lang/en_us.json +a0e7d027d022330c5358d75165a76383d86ba122 assets/create/lang/en_us.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -5321,7 +5321,7 @@ ad8fa04f7bbbafd70d0ce158af78a35e899301e2 data/create/tags/blocks/girdable_tracks 6e5d3b2123fbb00e7f439c091623619502551bca data/create/tags/blocks/non_movable.json 10781e8cfcbb3486327aace3aa00e437fb44b331 data/create/tags/blocks/ore_override_stone.json 760adb521c2e475a6414f97291f46c02d294fa74 data/create/tags/blocks/passive_boiler_heaters.json -af314e7ec90377e69387523a4c9af19e0056734e data/create/tags/blocks/safe_nbt.json +57f49df02be3d3cacaecf0315da34ea3fb614b8d data/create/tags/blocks/safe_nbt.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json d063e12c9ef75f39518c6d129ea35d833464d547 data/create/tags/blocks/toolboxes.json ad8fa04f7bbbafd70d0ce158af78a35e899301e2 data/create/tags/blocks/tracks.json diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index badbba0ef..8407d688d 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -2816,7 +2816,7 @@ "create.ponder.mechanical_roller_fill.text_5": "As opposed to 'clear & pave', neither of these modes will cause the rollers to break existing blocks", "create.ponder.mechanical_roller_pave.header": "Clearing and Paving with the Roller", - "create.ponder.mechanical_roller_pave.text_1": "Mechanical rollers help to clean up long tracks or paths conveniently", + "create.ponder.mechanical_roller_pave.text_1": "Mechanical rollers help to clean up terrain around tracks or paths", "create.ponder.mechanical_roller_pave.text_2": "In its default mode, without a material set, it will simply clear blocks like a Drill", "create.ponder.mechanical_roller_pave.text_3": "While disassembled, a suitable paving material can be specified", "create.ponder.mechanical_roller_pave.text_4": "Materials can be supplied via chests or barrels attached to the structure", diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 35e189c16..fa0877b19 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -230,7 +230,6 @@ import com.simibubi.create.content.logistics.block.vault.ItemVaultBlock; import com.simibubi.create.content.logistics.block.vault.ItemVaultCTBehaviour; import com.simibubi.create.content.logistics.block.vault.ItemVaultItem; import com.simibubi.create.content.logistics.item.LecternControllerBlock; -import com.simibubi.create.content.logistics.trains.BogeyRenderer; import com.simibubi.create.content.logistics.trains.BogeySizes; import com.simibubi.create.content.logistics.trains.TrackMaterial; import com.simibubi.create.content.logistics.trains.management.display.FlapDisplayBlock; @@ -1770,7 +1769,6 @@ public class AllBlocks { REGISTRATE.block("creative_crate", CreativeCrateBlock::new) .transform(BuilderTransformers.crate("creative")) .properties(p -> p.color(MaterialColor.COLOR_PURPLE)) - .tag(AllBlockTags.SAFE_NBT.tag) .register(); public static final BlockEntry DISPLAY_LINK = @@ -1866,7 +1864,6 @@ public class AllBlocks { public static final BlockEntry PLACARD = REGISTRATE.block("placard", PlacardBlock::new) .initialProperties(SharedProperties::copperMetal) .transform(pickaxeOnly()) - .tag(AllBlockTags.SAFE_NBT.tag) .blockstate((c, p) -> p.horizontalFaceBlock(c.get(), AssetLookup.standardModel(c, p))) .simpleItem() .register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java index 99a64bda6..b9b9692ec 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/SmartFluidPipeBlock.java @@ -93,8 +93,7 @@ public class SmartFluidPipeBlock extends FaceAttachedHorizontalDirectionalBlock boolean blockTypeChanged = state.getBlock() != newState.getBlock(); if (blockTypeChanged && !world.isClientSide) FluidPropagator.propagateChangedPipe(world, pos, state); - if (state.hasBlockEntity() && (blockTypeChanged || !newState.hasBlockEntity())) - world.removeBlockEntity(pos); + IBE.onRemove(state, world, pos, newState); } @Override diff --git a/src/main/java/com/simibubi/create/content/curiosities/clipboard/ClipboardScreen.java b/src/main/java/com/simibubi/create/content/curiosities/clipboard/ClipboardScreen.java index bfaf96d7a..bdda12df3 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/clipboard/ClipboardScreen.java +++ b/src/main/java/com/simibubi/create/content/curiosities/clipboard/ClipboardScreen.java @@ -442,7 +442,7 @@ public class ClipboardScreen extends AbstractSimiScreen { if (currentEntries.get(editingIndex).text.getString() .isEmpty() && currentEntries.size() > 1) { currentEntries.remove(editingIndex); - editingIndex -= 1; + editingIndex = Math.max(0, editingIndex - 1); editContext.setCursorToEnd(); return true; } else if (hasControlDown()) { diff --git a/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java index 67e1684f8..235ff5ae3 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java +++ b/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java @@ -1,12 +1,13 @@ package com.simibubi.create.content.schematics; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; +import com.simibubi.create.foundation.utility.NBTProcessors; + import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.decoration.ItemFrame; @@ -50,7 +51,9 @@ public class ItemRequirement { } public ItemRequirement(ItemUseType usage, List requiredItems) { - this(requiredItems.stream().map(req -> new StackRequirement(req, usage)).collect(Collectors.toList())); + this(requiredItems.stream() + .map(req -> new StackRequirement(req, usage)) + .collect(Collectors.toList())); } public static ItemRequirement of(BlockState state, BlockEntity be) { @@ -79,14 +82,18 @@ public class ItemRequirement { return INVALID; // double slab needs two items - if (state.hasProperty(BlockStateProperties.SLAB_TYPE) && state.getValue(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE) + if (state.hasProperty(BlockStateProperties.SLAB_TYPE) + && state.getValue(BlockStateProperties.SLAB_TYPE) == SlabType.DOUBLE) return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, 2)); if (block instanceof TurtleEggBlock) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(TurtleEggBlock.EGGS).intValue())); + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(TurtleEggBlock.EGGS) + .intValue())); if (block instanceof SeaPickleBlock) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SeaPickleBlock.PICKLES).intValue())); + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SeaPickleBlock.PICKLES) + .intValue())); if (block instanceof SnowLayerBlock) - return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SnowLayerBlock.LAYERS).intValue())); + return new ItemRequirement(ItemUseType.CONSUME, new ItemStack(item, state.getValue(SnowLayerBlock.LAYERS) + .intValue())); if (block instanceof FarmBlock || block instanceof DirtPathBlock) return new ItemRequirement(ItemUseType.CONSUME, Items.DIRT); if (block instanceof AbstractBannerBlock && be instanceof BannerBlockEntity bannerBE) @@ -101,22 +108,20 @@ public class ItemRequirement { if (entity instanceof ItemFrame itemFrame) { ItemStack frame = new ItemStack(Items.ITEM_FRAME); - ItemStack displayedItem = itemFrame.getItem(); + ItemStack displayedItem = NBTProcessors.withUnsafeNBTDiscarded(itemFrame.getItem()); if (displayedItem.isEmpty()) return new ItemRequirement(ItemUseType.CONSUME, Items.ITEM_FRAME); - return new ItemRequirement(ItemUseType.CONSUME, Arrays.asList(frame, displayedItem)); + return new ItemRequirement(List.of(new ItemRequirement.StackRequirement(frame, ItemUseType.CONSUME), + new ItemRequirement.StrictNbtStackRequirement(displayedItem, ItemUseType.CONSUME))); } if (entity instanceof ArmorStand armorStand) { - List requirements = new ArrayList<>(); - requirements.add(new ItemStack(Items.ARMOR_STAND)); - armorStand.getAllSlots().forEach(requirements::add); - return new ItemRequirement(ItemUseType.CONSUME, requirements); - } - - ItemStack pickedStack = entity.getPickResult(); - if (pickedStack != null) { - return new ItemRequirement(ItemUseType.CONSUME, pickedStack); + List requirements = new ArrayList<>(); + requirements.add(new StackRequirement(new ItemStack(Items.ARMOR_STAND), ItemUseType.CONSUME)); + armorStand.getAllSlots() + .forEach(s -> requirements + .add(new StrictNbtStackRequirement(NBTProcessors.withUnsafeNBTDiscarded(s), ItemUseType.CONSUME))); + return new ItemRequirement(requirements); } return INVALID; @@ -142,9 +147,8 @@ public class ItemRequirement { if (other.isEmpty()) return this; - return new ItemRequirement( - Stream.concat(requiredItems.stream(), other.requiredItems.stream()).collect(Collectors.toList()) - ); + return new ItemRequirement(Stream.concat(requiredItems.stream(), other.requiredItems.stream()) + .collect(Collectors.toList())); } public enum ItemUseType { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java index f36863473..fa5596abe 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java @@ -64,7 +64,7 @@ public class RollerScenes { scene.overlay.showText(60) .pointAt(util.vector.topOf(util.grid.at(6, 2, 4))) .attachKeyFrame() - .text("Mechanical rollers help to clean up long tracks or paths conveniently") + .text("Mechanical rollers help to clean up terrain around tracks or paths") .placeNearTarget(); scene.idle(70); diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java index 81a9357a4..f2dc7a70d 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java @@ -1,15 +1,20 @@ package com.simibubi.create.foundation.utility; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.function.UnaryOperator; import javax.annotation.Nullable; +import com.simibubi.create.AllBlockEntityTypes; + import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; +import net.minecraft.world.item.EnchantedBookItem; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.entity.SpawnerBlockEntity; @@ -23,7 +28,8 @@ public final class NBTProcessors { processors.put(type, processor); } - public static synchronized void addSurvivalProcessor(BlockEntityType type, UnaryOperator processor) { + public static synchronized void addSurvivalProcessor(BlockEntityType type, + UnaryOperator processor) { survivalProcessors.put(type, processor); } @@ -54,15 +60,62 @@ public final class NBTProcessors { } return data; }); + addProcessor(AllBlockEntityTypes.CREATIVE_CRATE.get(), itemProcessor("Filter")); + addProcessor(AllBlockEntityTypes.PLACARD.get(), itemProcessor("Item")); + } + + public static UnaryOperator itemProcessor(String tagKey) { + return data -> { + CompoundTag compound = data.getCompound(tagKey); + if (!compound.contains("tag", 10)) + return data; + CompoundTag itemTag = compound.getCompound("tag"); + if (itemTag == null) + return data; + HashSet keys = new HashSet<>(itemTag.getAllKeys()); + for (String key : keys) + if (isUnsafeItemNBTKey(key)) + itemTag.remove(key); + if (itemTag.isEmpty()) + compound.remove("tag"); + return data; + }; + } + + public static ItemStack withUnsafeNBTDiscarded(ItemStack stack) { + if (stack.getTag() == null) + return stack; + ItemStack copy = stack.copy(); + stack.getTag() + .getAllKeys() + .stream() + .filter(NBTProcessors::isUnsafeItemNBTKey) + .forEach(copy::removeTagKey); + if (copy.getTag() + .isEmpty()) + copy.setTag(null); + return copy; + } + + public static boolean isUnsafeItemNBTKey(String name) { + if (name.equals(EnchantedBookItem.TAG_STORED_ENCHANTMENTS)) + return false; + if (name.equals("Enchantments")) + return false; + if (name.contains("Potion")) + return false; + if (name.contains("Damage")) + return false; + return true; } public static boolean textComponentHasClickEvent(String json) { Component component = Component.Serializer.fromJson(json.isEmpty() ? "\"\"" : json); - return component != null && component.getStyle() != null && component.getStyle().getClickEvent() != null; + return component != null && component.getStyle() != null && component.getStyle() + .getClickEvent() != null; } - private NBTProcessors() { - } + private NBTProcessors() {} @Nullable public static CompoundTag process(BlockEntity blockEntity, CompoundTag compound, boolean survival) {