diff --git a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java index d004d9ae2..07ba16454 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/Contraption.java @@ -1139,6 +1139,7 @@ public abstract class Contraption { if (blockEntity instanceof IMultiBlockEntityContainer) { if (tag.contains("LastKnownPos") || capturedMultiblocks.isEmpty()) { tag.put("LastKnownPos", NbtUtils.writeBlockPos(BlockPos.ZERO.below(Integer.MAX_VALUE - 1))); + tag.remove("Controller"); } } @@ -1195,6 +1196,9 @@ public abstract class Contraption { // swap nbt data to the new controller position StructureBlockInfo prevControllerInfo = blocks.get(controllerPos); StructureBlockInfo newControllerInfo = blocks.get(otherPos); + if (prevControllerInfo == null || newControllerInfo == null) + return; + blocks.put(otherPos, new StructureBlockInfo(newControllerInfo.pos, newControllerInfo.state, prevControllerInfo.nbt)); blocks.put(controllerPos, new StructureBlockInfo(prevControllerInfo.pos, prevControllerInfo.state, newControllerInfo.nbt)); }); diff --git a/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java b/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java index b11625687..724bab243 100644 --- a/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/kinetics/base/GeneratingKineticBlockEntity.java @@ -73,9 +73,8 @@ public abstract class GeneratingKineticBlockEntity extends KineticBlockEntity { float speed = getTheoreticalSpeed(); if (speed != getGeneratedSpeed() && speed != 0) stressBase *= getGeneratedSpeed() / speed; - speed = Math.abs(speed); - float stressTotal = stressBase * speed; + float stressTotal = Math.abs(stressBase * speed); Lang.number(stressTotal) .translate("generic.unit.stress") diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java index b5db5c057..544135261 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/source/DisplaySource.java @@ -13,6 +13,7 @@ import com.simibubi.create.content.trains.display.FlapDisplayBlockEntity; import com.simibubi.create.content.trains.display.FlapDisplayLayout; import com.simibubi.create.foundation.gui.ModularGuiLineBuilder; import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.NBTProcessors; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; @@ -38,6 +39,12 @@ public abstract class DisplaySource extends DisplayBehaviour { List text = provideText(context, stats); if (text.isEmpty()) text = EMPTY; + + if (activeTarget.requiresComponentSanitization()) + for (MutableComponent component : text) + if (NBTProcessors.textComponentHasClickEvent(component)) + return; // Naughty + activeTarget.acceptText(line, text, context); } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java index 7732f7be2..79b2e128a 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/DisplayTarget.java @@ -67,5 +67,9 @@ public abstract class DisplayTarget extends DisplayBehaviour { tag.remove("DisplayLink"); return false; } + + public boolean requiresComponentSanitization() { + return false; + } } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java index fdc087b4f..15ec2a072 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/LecternDisplayTarget.java @@ -80,5 +80,10 @@ public class LecternDisplayTarget extends DisplayTarget { return written; } + + @Override + public boolean requiresComponentSanitization() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java index 77efd5436..21e4f224b 100644 --- a/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java +++ b/src/main/java/com/simibubi/create/content/redstone/displayLink/target/SignDisplayTarget.java @@ -35,5 +35,10 @@ public class SignDisplayTarget extends DisplayTarget { public DisplayTargetStats provideStats(DisplayLinkContext context) { return new DisplayTargetStats(4, 15, this); } + + @Override + public boolean requiresComponentSanitization() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java index 4bbca4a6f..c637a4473 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java @@ -10,6 +10,8 @@ import java.util.function.Predicate; import java.util.stream.Stream; import com.simibubi.create.Create; +import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.utility.BBHelper; import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; @@ -250,5 +252,25 @@ public class SchematicWorld extends WrappedWorld implements ServerLevelAccessor } throw new IllegalStateException("Cannot use IServerWorld#getWorld in a client environment"); } + + public void fixControllerBlockEntities() { + for (BlockEntity blockEntity : blockEntities.values()) { + if (!(blockEntity instanceof IMultiBlockEntityContainer multiBlockEntity)) + continue; + BlockPos lastKnown = multiBlockEntity.getLastKnownPos(); + BlockPos current = blockEntity.getBlockPos(); + if (lastKnown == null || current == null) + continue; + if (multiBlockEntity.isController()) + continue; + if (!lastKnown.equals(current)) { + BlockPos newControllerPos = multiBlockEntity.getController() + .offset(current.subtract(lastKnown)); + if (multiBlockEntity instanceof SmartBlockEntity sbe) + sbe.markVirtual(); + multiBlockEntity.setController(newControllerPos); + } + } + } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java index cbc9b1958..5cdfac880 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java @@ -168,6 +168,7 @@ public class SchematicHandler { schematic.placeInWorld(w, pos, pos, placementSettings, w.getRandom(), Block.UPDATE_CLIENTS); for (BlockEntity blockEntity : w.getBlockEntities()) blockEntity.setLevel(w); + w.fixControllerBlockEntities(); } catch (Exception e) { Minecraft.getInstance().player.displayClientMessage(Lang.translate("schematic.error") .component(), false); @@ -182,6 +183,7 @@ public class SchematicHandler { placementSettings.getMirror()); for (BlockEntity be : wMirroredFB.getRenderedBlockEntities()) transform.apply(be); + wMirroredFB.fixControllerBlockEntities(); placementSettings.setMirror(Mirror.LEFT_RIGHT); pos = BlockPos.ZERO.south(size.getZ() - 1); @@ -190,6 +192,7 @@ public class SchematicHandler { placementSettings.getMirror()); for (BlockEntity be : wMirroredLR.getRenderedBlockEntities()) transform.apply(be); + wMirroredLR.fixControllerBlockEntities(); renderers.get(0) .display(w); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java index c719fa374..e6e6e8ccd 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java @@ -14,7 +14,6 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.content.kinetics.belt.BeltBlock; import com.simibubi.create.content.kinetics.belt.BeltBlockEntity; import com.simibubi.create.content.schematics.SchematicWorld; -import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; import com.simibubi.create.foundation.mixin.accessor.ParticleEngineAccessor; import com.simibubi.create.foundation.ponder.element.WorldSectionElement; @@ -252,38 +251,22 @@ public class PonderWorld extends SchematicWorld { smartBlockEntity.markVirtual(); } + @Override public void fixControllerBlockEntities() { + super.fixControllerBlockEntities(); for (BlockEntity blockEntity : blockEntities.values()) { - - if (blockEntity instanceof BeltBlockEntity) { - BeltBlockEntity beltBlockEntity = (BeltBlockEntity) blockEntity; - if (!beltBlockEntity.isController()) + if (!(blockEntity instanceof BeltBlockEntity beltBlockEntity)) + continue; + if (!beltBlockEntity.isController()) + continue; + BlockPos controllerPos = blockEntity.getBlockPos(); + for (BlockPos blockPos : BeltBlock.getBeltChain(this, controllerPos)) { + BlockEntity blockEntity2 = getBlockEntity(blockPos); + if (!(blockEntity2 instanceof BeltBlockEntity)) continue; - BlockPos controllerPos = blockEntity.getBlockPos(); - for (BlockPos blockPos : BeltBlock.getBeltChain(this, controllerPos)) { - BlockEntity blockEntity2 = getBlockEntity(blockPos); - if (!(blockEntity2 instanceof BeltBlockEntity)) - continue; - BeltBlockEntity belt2 = (BeltBlockEntity) blockEntity2; - belt2.setController(controllerPos); - } + BeltBlockEntity belt2 = (BeltBlockEntity) blockEntity2; + belt2.setController(controllerPos); } - - if (blockEntity instanceof IMultiBlockEntityContainer) { - IMultiBlockEntityContainer multiBlockEntity = (IMultiBlockEntityContainer) blockEntity; - BlockPos lastKnown = multiBlockEntity.getLastKnownPos(); - BlockPos current = blockEntity.getBlockPos(); - if (lastKnown == null || current == null) - continue; - if (multiBlockEntity.isController()) - continue; - if (!lastKnown.equals(current)) { - BlockPos newControllerPos = multiBlockEntity.getController() - .offset(current.subtract(lastKnown)); - multiBlockEntity.setController(newControllerPos); - } - } - } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java index 11a426e3f..a07dd895d 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -12,6 +12,7 @@ import com.simibubi.create.content.kinetics.base.KineticBlockEntity; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.foundation.blockEntity.IMergeableBE; +import com.simibubi.create.foundation.blockEntity.IMultiBlockEntityContainer; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -19,6 +20,7 @@ import net.minecraft.core.Registry; import net.minecraft.core.SectionPos; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -316,8 +318,11 @@ public class BlockHelper { data.putInt("x", target.getX()); data.putInt("y", target.getY()); data.putInt("z", target.getZ()); - if (blockEntity instanceof KineticBlockEntity) - ((KineticBlockEntity) blockEntity).warnOfMovement(); + if (blockEntity instanceof KineticBlockEntity kbe) + kbe.warnOfMovement(); + if (blockEntity instanceof IMultiBlockEntityContainer imbe) + if (!imbe.isController()) + data.put("Controller", NbtUtils.writeBlockPos(imbe.getController())); blockEntity.load(data); } } 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 eab609906..412108c1d 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.utility; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.function.UnaryOperator; @@ -57,6 +58,24 @@ public final class NBTProcessors { }); addProcessor(AllBlockEntityTypes.CREATIVE_CRATE.get(), itemProcessor("Filter")); addProcessor(AllBlockEntityTypes.PLACARD.get(), itemProcessor("Item")); + addProcessor(AllBlockEntityTypes.CLIPBOARD.get(), data -> { + if (!data.contains("Item", Tag.TAG_COMPOUND)) + return data; + CompoundTag book = data.getCompound("Item"); + + if (!book.contains("tag", Tag.TAG_COMPOUND)) + return data; + CompoundTag itemData = book.getCompound("tag"); + + for (List entries : NBTHelper.readCompoundList(itemData.getList("Pages", Tag.TAG_COMPOUND), + pageTag -> NBTHelper.readCompoundList(pageTag.getList("Entries", Tag.TAG_COMPOUND), + tag -> tag.getString("Text")))) { + for (String entry : entries) + if (textComponentHasClickEvent(entry)) + return null; + } + return data; + }); } // Triggered by block tag, not BE type @@ -120,7 +139,13 @@ public final class NBTProcessors { } public static boolean textComponentHasClickEvent(String json) { - Component component = Component.Serializer.fromJson(json.isEmpty() ? "\"\"" : json); + return textComponentHasClickEvent(Component.Serializer.fromJson(json.isEmpty() ? "\"\"" : json)); + } + + public static boolean textComponentHasClickEvent(Component component) { + for (Component sibling : component.getSiblings()) + if (textComponentHasClickEvent(sibling)) + return true; return component != null && component.getStyle() != null && component.getStyle() .getClickEvent() != null; } @@ -144,7 +169,7 @@ public final class NBTProcessors { return signProcessor.apply(compound); if (blockEntity.onlyOpCanSetNbt()) return null; - return withUnsafeNBTDiscarded(compound); + return compound; } }