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
This commit is contained in:
simibubi 2023-05-11 14:15:56 +02:00
parent 3e9074cddc
commit 8e03372bb3
8 changed files with 87 additions and 34 deletions

View File

@ -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

View File

@ -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",

View File

@ -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<DisplayLinkBlock> DISPLAY_LINK =
@ -1866,7 +1864,6 @@ public class AllBlocks {
public static final BlockEntry<PlacardBlock> 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();

View File

@ -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

View File

@ -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()) {

View File

@ -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<ItemStack> 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<ItemStack> 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<StackRequirement> 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 {

View File

@ -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);

View File

@ -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<CompoundTag> processor) {
public static synchronized void addSurvivalProcessor(BlockEntityType<?> type,
UnaryOperator<CompoundTag> 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<CompoundTag> 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<String> 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) {