diff --git a/src/main/java/team/creative/littletiles/client/level/LevelHandlersClient.java b/src/main/java/team/creative/littletiles/client/level/LevelHandlersClient.java index d952e2067..612059869 100644 --- a/src/main/java/team/creative/littletiles/client/level/LevelHandlersClient.java +++ b/src/main/java/team/creative/littletiles/client/level/LevelHandlersClient.java @@ -36,13 +36,14 @@ public void load(LevelEvent.Load event) { for (int i = 0; i < handlers.size(); i++) handlers.get(i).load((Level) event.getLevel()); - - awareHandlers.forEach(x -> x.unload()); + } public void unload(ClientPlayerNetworkEvent.LoggingOut event) { for (int i = 0; i < handlers.size(); i++) handlers.get(i).unload(); + + awareHandlers.forEach(x -> x.unload()); } private static record LevelHandlerClient(Function factory, Consumer consumer) { diff --git a/src/main/java/team/creative/littletiles/client/render/cache/build/RenderingThread.java b/src/main/java/team/creative/littletiles/client/render/cache/build/RenderingThread.java index 32828c573..963281546 100644 --- a/src/main/java/team/creative/littletiles/client/render/cache/build/RenderingThread.java +++ b/src/main/java/team/creative/littletiles/client/render/cache/build/RenderingThread.java @@ -58,6 +58,7 @@ public static synchronized void initThreads(int count) { while (QUEUE.size() > 0) QUEUE.poll().be.render.resetRenderingState(); + QUEUE.clear(); // Make sure all levels and sections are reset } THREADS = new ArrayList<>(); for (int i = 0; i < count; i++) diff --git a/src/main/java/team/creative/littletiles/common/action/LittleAction.java b/src/main/java/team/creative/littletiles/common/action/LittleAction.java index eece02d8e..0b93e74fd 100644 --- a/src/main/java/team/creative/littletiles/common/action/LittleAction.java +++ b/src/main/java/team/creative/littletiles/common/action/LittleAction.java @@ -185,16 +185,17 @@ else if (blockEntity == null && shouldConvert) { return b; return null; } - - public static void fireBlockBreakEvent(Level level, BlockPos pos, Player player) throws AreaProtected { + + public static boolean fireBlockBreakEvent(Level level, BlockPos pos, Player player) { if (level.isClientSide) - return; + return true; BreakEvent event = new BlockEvent.BreakEvent(level, pos, level.getBlockState(pos), player); MinecraftForge.EVENT_BUS.post(event); if (event.isCanceled()) { sendBlockResetToClient(level, player, pos); - throw new AreaProtected(); + return false; } + return true; } private static Method loadWorldEditEvent() { @@ -435,24 +436,23 @@ public static List getInventories(Player player) { } private static boolean isBlockValid(Block block) { - if (block instanceof EntityBlock || block instanceof SlabBlock) - return false; if (LittleBlockRegistry.isSpecialBlock(block)) return true; return block instanceof GlassBlock || block instanceof StainedGlassBlock || block instanceof HalfTransparentBlock || block instanceof LeavesBlock; } private static boolean isBlockInvalid(Block block) { + if (block instanceof EntityBlock || block instanceof SlabBlock) + return true; var location = block.builtInRegistryHolder().unwrapKey().get().location(); return location.getNamespace().equals("framedblocks"); } public static boolean isBlockValid(BlockState state) { - if (isBlockValid(state.getBlock())) - return true; if (isBlockInvalid(state.getBlock())) return false; - + if (isBlockValid(state.getBlock())) + return true; if (state.isSolid() && state.isCollisionShapeFullBlock(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) return true; if (ChiselsAndBitsManager.isChiselsAndBitsStructure(state)) diff --git a/src/main/java/team/creative/littletiles/common/action/LittleActionBoxes.java b/src/main/java/team/creative/littletiles/common/action/LittleActionBoxes.java index 5530be8af..29ed94e3c 100644 --- a/src/main/java/team/creative/littletiles/common/action/LittleActionBoxes.java +++ b/src/main/java/team/creative/littletiles/common/action/LittleActionBoxes.java @@ -23,6 +23,7 @@ import team.creative.littletiles.LittleTiles; import team.creative.littletiles.common.block.entity.BETiles; import team.creative.littletiles.common.config.LittleBuildingConfig; +import team.creative.littletiles.common.config.LittleTilesConfig; import team.creative.littletiles.common.config.LittleTilesConfig.NotAllowedToEditException; import team.creative.littletiles.common.entity.LittleEntity; import team.creative.littletiles.common.grid.LittleGrid; @@ -95,6 +96,7 @@ else if (LittleAction.isBlockValid(state) && LittleAction.canConvertBlock(player sendBlockResetToClient(level, player, pos); throw e; } + boolean areaProtected = false; for (Iterator>> iterator = boxesMap.entrySet().iterator(); iterator.hasNext();) { Entry> entry = iterator.next(); @@ -105,6 +107,10 @@ else if (LittleAction.isBlockValid(state) && LittleAction.canConvertBlock(player sendBlockResetToClient(level, player, pos); continue; } + if (requiresBreak() && !fireBlockBreakEvent(level, pos, player)) { + areaProtected = true; + continue; + } action(level, player, pos, state, entry.getValue(), boxes.grid); } @@ -112,6 +118,8 @@ else if (LittleAction.isBlockValid(state) && LittleAction.canConvertBlock(player actionDone(level, player); level.playSound(null, player, SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, 1, 1); + if (areaProtected) + throw new LittleTilesConfig.AreaProtected(); return true; } @@ -132,5 +140,8 @@ public boolean wasSuccessful(Boolean result) { public Boolean failed() { return false; } - + + public boolean requiresBreak() { + return true; + } } diff --git a/src/main/java/team/creative/littletiles/common/action/LittleActionInteract.java b/src/main/java/team/creative/littletiles/common/action/LittleActionInteract.java index e748e1a7f..0d19931ec 100644 --- a/src/main/java/team/creative/littletiles/common/action/LittleActionInteract.java +++ b/src/main/java/team/creative/littletiles/common/action/LittleActionInteract.java @@ -21,6 +21,7 @@ import team.creative.littletiles.client.action.LittleActionHandlerClient; import team.creative.littletiles.common.block.entity.BETiles; import team.creative.littletiles.common.block.little.tile.LittleTileContext; +import team.creative.littletiles.common.config.LittleTilesConfig; import team.creative.littletiles.common.entity.LittleEntity; public abstract class LittleActionInteract extends LittleAction { @@ -102,9 +103,9 @@ public T action(Player player) throws LittleActionException { transformedCoordinates = true; } } - - if (requiresBreakEvent()) - fireBlockBreakEvent(level, blockPos, player); + + if (requiresBreakEvent() && !fireBlockBreakEvent(level, blockPos, player)) + throw new LittleTilesConfig.AreaProtected(); BlockEntity blockEntity = level.getBlockEntity(blockPos); if (blockEntity instanceof BETiles be) { diff --git a/src/main/java/team/creative/littletiles/common/block/entity/BETiles.java b/src/main/java/team/creative/littletiles/common/block/entity/BETiles.java index 39be6a6d3..46f12666e 100644 --- a/src/main/java/team/creative/littletiles/common/block/entity/BETiles.java +++ b/src/main/java/team/creative/littletiles/common/block/entity/BETiles.java @@ -479,7 +479,13 @@ protected int[] getIdentifier(LittleBox box) { public void saveAdditional(CompoundTag nbt) { super.saveAdditional(nbt); grid.set(nbt); - nbt.put("content", tiles.save(new LittleServerFace(this))); + + //add null value when tiles is null,this will cause NPE in some hybrid server + if (tiles == null) { + nbt.put("content", new CompoundTag()); + } else { + nbt.put("content", tiles.save(new LittleServerFace(this))); + } sideCache.write(nbt); } diff --git a/src/main/java/team/creative/littletiles/common/block/little/tile/group/LittleGroup.java b/src/main/java/team/creative/littletiles/common/block/little/tile/group/LittleGroup.java index ee41a9e8d..6d8d7fd1d 100644 --- a/src/main/java/team/creative/littletiles/common/block/little/tile/group/LittleGroup.java +++ b/src/main/java/team/creative/littletiles/common/block/little/tile/group/LittleGroup.java @@ -372,7 +372,7 @@ public void convertTo(LittleGrid to) { } public LittleGroup copyExceptChildren() { - LittleGroup group = new LittleGroup(structure, Collections.EMPTY_LIST); + LittleGroup group = new LittleGroup(structure != null ? structure.copy() : null, Collections.EMPTY_LIST); for (Entry extension : children.extensionEntries()) group.children.addExtension(extension.getKey(), extension.getValue().copy()); group.addAll(grid, new FunctionIterator<>(this, x -> x.copy())); @@ -383,7 +383,7 @@ public LittleGroup copy() { List newChildren = new ArrayList<>(); for (LittleGroup group : children.children()) newChildren.add(group.copy()); - LittleGroup group = new LittleGroup(structure, newChildren); + LittleGroup group = new LittleGroup(structure != null ? structure.copy() : null, newChildren); for (Entry extension : children.extensionEntries()) group.children.addExtension(extension.getKey(), extension.getValue().copy()); group.addAll(grid, new FunctionIterator<>(this, x -> x.copy())); diff --git a/src/main/java/team/creative/littletiles/common/block/little/tile/parent/StructureParentCollection.java b/src/main/java/team/creative/littletiles/common/block/little/tile/parent/StructureParentCollection.java index 3aee09e79..35f29f9c3 100644 --- a/src/main/java/team/creative/littletiles/common/block/little/tile/parent/StructureParentCollection.java +++ b/src/main/java/team/creative/littletiles/common/block/little/tile/parent/StructureParentCollection.java @@ -116,7 +116,14 @@ public LittleStructure setStructureNBT(CompoundTag nbt) { } return (LittleStructure) cache; } - + + @Override + public LittleStructure getStructureUncached() throws CorruptedConnectionException, NotYetConnectedException { + if (!isMain()) // Make sure not to remove the structure + cache = null; + return getStructure(); + } + @Override public LittleStructure getStructure() throws CorruptedConnectionException, NotYetConnectedException { if (isMain()) diff --git a/src/main/java/team/creative/littletiles/common/convertion/OldLittleTilesDataParser.java b/src/main/java/team/creative/littletiles/common/convertion/OldLittleTilesDataParser.java index 5b5c8d4e1..d774f6319 100644 --- a/src/main/java/team/creative/littletiles/common/convertion/OldLittleTilesDataParser.java +++ b/src/main/java/team/creative/littletiles/common/convertion/OldLittleTilesDataParser.java @@ -17,6 +17,7 @@ import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.registries.ForgeRegistries; import team.creative.creativecore.common.util.math.base.Axis; import team.creative.creativecore.common.util.math.base.Facing; import team.creative.creativecore.common.util.math.vec.Vec1d; @@ -78,7 +79,34 @@ public static LittleTile createTile(CompoundTag nbt) { int color = -1; if (nbt.contains("color")) color = nbt.getInt("color"); - return new LittleTile(BLOCK_MAP.getOrDefault(name, name), color, Collections.EMPTY_LIST); + + String newId = resolveBlockState(name); + return new LittleTile(newId, color, Collections.EMPTY_LIST); + } + + private static String resolveBlockState(String name) { + String mapped = BLOCK_MAP.get(name); + if (mapped != null) return mapped; + + LittleTiles.LOGGER.warn("Block not in 1.12.2.txt, trying to extract name: {}", name); + String base = extractBaseId(name); // minecraft:bone_block:1:1:1 → minecraft:bone_block + ResourceLocation loc = ResourceLocation.tryParse(base); + if (loc != null && ForgeRegistries.BLOCKS.containsKey(loc)) { + return loc.toString(); // block ID, no meta data + } + + // missing + LittleTiles.LOGGER.warn("fail to extract name, will use missing/magenta texture: {}", name); + return name; + } + + //ignore data after the second ":" + private static String extractBaseId(String name) { + LittleTiles.LOGGER.warn("converting:"+name); + int cut = name.indexOf(':'); + if (cut == -1) return name; + int next = name.indexOf(':', cut + 1); + return next == -1 ? name : name.substring(0, next); } public static LittleGroup load(CompoundTag nbt) throws LittleConvertException { @@ -126,8 +154,10 @@ public static LittleGroup loadGroup(CompoundTag nbt, LittleGrid grid) throws Lit private static void convertDoorBaseData(CompoundTag oldData, CompoundTag newData) { convertStructureDataBase(oldData, newData); - - newData.put("state", oldData.get("state")); + + var state = oldData.get("state"); + if (state != null) + newData.put("state", state); newData.putBoolean("actP", oldData.getBoolean("activateParent")); newData.putBoolean("hand", !oldData.getBoolean("disableRightClick")); @@ -393,10 +423,18 @@ public static CompoundTag convertStructureData(CompoundTag nbt) throws LittleCon converted.putString("id", "door"); yield converted; } - default -> throw new LittleConvertException("Cannot convert " + nbt.getString("id") + " yet"); + default -> throw new LittleMissingStructureException("Cannot convert " + nbt.getString("id") + " yet"); }; } - + + public static class LittleMissingStructureException extends LittleConvertException { + + public LittleMissingStructureException(String name) { + super(name); + } + + } + public static CompoundTag convert(CompoundTag nbt) throws LittleConvertException { return LittleGroup.save(load(nbt)); } diff --git a/src/main/java/team/creative/littletiles/common/entity/animation/LittleAnimationLevel.java b/src/main/java/team/creative/littletiles/common/entity/animation/LittleAnimationLevel.java index ab1fde867..b311a938d 100644 --- a/src/main/java/team/creative/littletiles/common/entity/animation/LittleAnimationLevel.java +++ b/src/main/java/team/creative/littletiles/common/entity/animation/LittleAnimationLevel.java @@ -512,4 +512,14 @@ public boolean addFreshEntity(Entity entity) { } return false; } + + @Override + public int getMinBuildHeight() { + return parentLevel.getMinBuildHeight(); + } + + @Override + public int getHeight() { + return parentLevel.getHeight(); + } } diff --git a/src/main/java/team/creative/littletiles/common/gui/controls/animation/GuiAnimationTimelinePanel.java b/src/main/java/team/creative/littletiles/common/gui/controls/animation/GuiAnimationTimelinePanel.java index e2b855c28..039b7782a 100644 --- a/src/main/java/team/creative/littletiles/common/gui/controls/animation/GuiAnimationTimelinePanel.java +++ b/src/main/java/team/creative/littletiles/common/gui/controls/animation/GuiAnimationTimelinePanel.java @@ -251,9 +251,10 @@ protected ValueCurve parse(Iterable> keys, ValueIn public AnimationTimeline generateTimeline(int duration, ValueInterpolation interpolation) { List events = new ArrayList<>(); for (GuiChildTimelineChannel channel : childChannels) - for (GuiTimelineKey key : channel.keys()) - if (key.tick <= duration) - events.add(new AnimationEventEntry(key.tick, key.value)); + if (channel != null) + for (GuiTimelineKey key : channel.keys()) + if (key.tick <= duration) + events.add(new AnimationEventEntry(key.tick, key.value)); for (GuiSoundTimelineChannel channel : soundChannels) for (GuiTimelineKey key : channel.keys()) diff --git a/src/main/java/team/creative/littletiles/common/gui/signal/GuiSignalController.java b/src/main/java/team/creative/littletiles/common/gui/signal/GuiSignalController.java index 5be18bd34..47d822929 100644 --- a/src/main/java/team/creative/littletiles/common/gui/signal/GuiSignalController.java +++ b/src/main/java/team/creative/littletiles/common/gui/signal/GuiSignalController.java @@ -36,6 +36,7 @@ import team.creative.creativecore.common.util.type.itr.FilterIterator; import team.creative.creativecore.common.util.type.itr.FilterListIterator; import team.creative.creativecore.common.util.type.itr.NestedIterator; +import team.creative.littletiles.LittleTiles; import team.creative.littletiles.common.gui.signal.dialog.GuiDialogSignal; import team.creative.littletiles.common.gui.signal.node.GuiSignalNode; import team.creative.littletiles.common.gui.signal.node.GuiSignalNodeInput; @@ -308,7 +309,7 @@ public void mouseReleased(Rect rect, double x, double y, int button) { public void setOutput(int cell, GuiSignalComponent output) { if (this.output != null) - removeNode(this.output); + this.output.remove(); //removeNode(this.output); this.output = new GuiSignalNodeOutput(output); setToFreeCell(cell, this.output); raiseEvent(new GuiControlChangedEvent(this)); @@ -331,6 +332,7 @@ public void setCondition(SignalInputCondition condition, GuiDialogSignal signal) output.connect(connection); return; } catch (ParseException e) { + LittleTiles.LOGGER.catching(e); reset(); } setOutput(4, output.component); @@ -499,6 +501,7 @@ public void set(GuiSignalNode node, int col, int row) { public void reset() { controls.clear(); grid.clear(); + output.remove(); dragged = null; selected = null;; } diff --git a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignal.java b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignal.java index 7e5d92ef1..53a6e731f 100644 --- a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignal.java +++ b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignal.java @@ -24,6 +24,7 @@ import team.creative.littletiles.common.gui.signal.GuiSignalComponent; import team.creative.littletiles.common.gui.signal.GuiSignalController; import team.creative.littletiles.common.gui.signal.IConditionConfiguration; +import team.creative.littletiles.common.structure.signal.component.SignalComponentType; import team.creative.littletiles.common.structure.signal.input.SignalInputCondition; import team.creative.littletiles.common.structure.signal.logic.SignalLogicOperator; import team.creative.littletiles.common.structure.signal.logic.SignalMode; @@ -35,7 +36,7 @@ public class GuiDialogSignal extends GuiLayer { public List inputs; public GuiDialogSignal() { - super("gui.dialog.signal", 320, 200); + super("gui.dialog.signal", 420, 300); flow = GuiFlow.STACK_Y; registerEventChanged(this::changed); } @@ -137,7 +138,7 @@ public GuiSignalComponent getInput(SignalTarget target) throws ParseException { for (GuiSignalComponent component : inputs) if (component.name().equals(target.writeBase())) return component; - throw new ParseException("input not found", 0); + return new GuiSignalComponent("lost?", target.write(), 1, SignalComponentType.INVALID, false, 0); } public void modeChanged() { diff --git a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalEvents.java b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalEvents.java index b09f50922..eed5483aa 100644 --- a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalEvents.java +++ b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalEvents.java @@ -162,7 +162,7 @@ public void update() { int delay = modeConfig.delay; if (condition != null) delay = Math.max(delay, (int) Math.ceil(condition.calculateDelay())); - mode.setTitle(Component.translatable(modeConfig.getMode().translateKey).append(" ").append(Component.translatable("gui.delay")).append(": " + delay)); + mode.setTitle(modeConfig.description(delay)); } public SignalOutputHandler getHandler(ISignalComponent component, LittleStructure structure) { diff --git a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalInput.java b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalInput.java index 48a8bcc3d..ea3bf3c58 100644 --- a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalInput.java +++ b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalInput.java @@ -34,8 +34,9 @@ public class GuiDialogSignalInput extends GuiLayer { public int bandwidth; public GuiDialogSignalInput() { - super("gui.dialog.signal.input", 100, 100); + super("gui.dialog.signal.input", 200, 100); flow = GuiFlow.STACK_Y; + registerEventChanged(this::changed); } public void init(GuiSignalNodeInput input) { @@ -126,7 +127,7 @@ public void save(GuiSignalNodeInput input, GuiParent panel) { } }); - upper.add(new GuiTabButtonMapped("type", input.operator, new TextMapBuilder().addComponent(modes, x -> x.translatable()))); + add(new GuiTabButtonMapped("type", input.operator, new TextMapBuilder().addComponent(modes, x -> x.translatable()))); add(new GuiScrollY("config").setExpandable()); GuiLeftRightBox bottom = new GuiLeftRightBox(); diff --git a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalVirtualInput.java b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalVirtualInput.java index 80c999f28..d81bcd68b 100644 --- a/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalVirtualInput.java +++ b/src/main/java/team/creative/littletiles/common/gui/signal/dialog/GuiDialogSignalVirtualInput.java @@ -33,7 +33,7 @@ public class GuiDialogSignalVirtualInput extends GuiLayer { public GuiVirtualInputIndexConfiguration[] config; public GuiDialogSignalVirtualInput() { - super("gui.dialog.signal.virtual_input", 130, 100); + super("gui.dialog.signal.virtual_input", 230, 200); flow = GuiFlow.STACK_Y; registerEventChanged(this::changed); } diff --git a/src/main/java/team/creative/littletiles/common/gui/tool/GuiBag.java b/src/main/java/team/creative/littletiles/common/gui/tool/GuiBag.java index 980e99e0e..cffb9dc1f 100644 --- a/src/main/java/team/creative/littletiles/common/gui/tool/GuiBag.java +++ b/src/main/java/team/creative/littletiles/common/gui/tool/GuiBag.java @@ -45,7 +45,7 @@ public class GuiBag extends GuiConfigure { public SimpleContainer input = new SimpleContainer(1); private List inventories = new ArrayList<>(); private List inventoriesInv = new ArrayList<>(); - + public final GuiSyncLocal RELOAD = getSyncHolder().register("reload", v -> { tool.changed(); reinit(); @@ -193,7 +193,7 @@ public void create() { addInventory(inputInventory); addInventory(bagInventoryGui); } - + public void clearItemCache() { for (int i = 0; i < bagInventoryGui.inventorySize(); i++) ((BagSlot) bagInventoryGui.getSlot(i).slot).resetCache(); @@ -293,12 +293,13 @@ public ItemStack remove(int count) { entry.value -= taken.getCount(); } else entry.value = 0; - + if (entry.isEmpty()) bag.get(BlockIngredient.class).getContent().remove(getSlotIndex()); } cache = null; saveBagInventory(); + clearItemCache(); return taken; } } diff --git a/src/main/java/team/creative/littletiles/common/gui/tool/recipe/GuiRecipe.java b/src/main/java/team/creative/littletiles/common/gui/tool/recipe/GuiRecipe.java index 19c2443ba..b980e893a 100644 --- a/src/main/java/team/creative/littletiles/common/gui/tool/recipe/GuiRecipe.java +++ b/src/main/java/team/creative/littletiles/common/gui/tool/recipe/GuiRecipe.java @@ -224,13 +224,13 @@ public void updateTree() { sidebar.add(sidebarButtons.setAlign(Align.CENTER)); sidebarButtons.add(new GuiButton("add", x -> OPEN_ADD.open(new CompoundTag()).init(this)).setTranslate("gui.plus").setAlign(Align.CENTER).setVAlign(VAlign.CENTER).setDim( - 12, 12).setTooltip(new TextBuilder().translate("gui.recipe.add").build())); + 15, 15).setTooltip(new TextBuilder().translate("gui.recipe.add").build())); sidebarButtons.add(new GuiButtonIcon("duplicate", Icon.DUPLICATE, x -> { if (tree.selected() == null) return; tree.selected().getParentItem().addItem(((GuiTreeItemStructure) tree.selected()).duplicate()); tree.updateTree(); - }).setTooltip(new TextBuilder().translate("gui.recipe.duplicate").build())); + }).setDim(15, 15).setTooltip(new TextBuilder().translate("gui.recipe.duplicate").build())); sidebarButtons.add(new GuiButton("del", x -> { if (tree.selected() == null) return; @@ -239,14 +239,15 @@ public void updateTree() { if (b == DialogButton.YES) removeItem((GuiTreeItemStructure) tree.selected()); }, DialogButton.NO, DialogButton.YES); - }).setTranslate("gui.del").setAlign(Align.CENTER).setVAlign(VAlign.CENTER).setDim(12, 12).setTooltip(new TextBuilder().translate("gui.recipe.delete").build())); - sidebarButtons.add(new GuiButtonIcon("up", Icon.ARROW_UP, x -> tree.moveUp()).setTooltip(new TextBuilder().translate("gui.recipe.moveup").build())); - sidebarButtons.add(new GuiButtonIcon("down", Icon.ARROW_DOWN, x -> tree.moveDown()).setTooltip(new TextBuilder().translate("gui.recipe.movedown").build())); - - sidebarButtons.add(new GuiButtonIcon("move", Icon.MOVE, x -> OPEN_MOVE.open(new CompoundTag()).init(this)).setTooltip(new TextBuilder().translate("gui.recipe.move") - .build())); - sidebarButtons.add(new GuiButtonIcon("merge", Icon.MERGE, x -> OPEN_MERGE.open(new CompoundTag()).init(this)).setTooltip(new TextBuilder().translate("gui.recipe.merge") - .build())); + }).setTranslate("gui.del").setAlign(Align.CENTER).setVAlign(VAlign.CENTER).setDim(15, 15).setTooltip(new TextBuilder().translate("gui.recipe.delete").build())); + + sidebarButtons.add(new GuiButtonIcon("move", Icon.MOVE, x -> OPEN_MOVE.open(new CompoundTag()).init(this)).setDim(15, 15).setTooltip(new TextBuilder().translate( + "gui.recipe.move").build())); + + sidebarButtons.add(new GuiButtonIcon("up", Icon.ARROW_UP, x -> tree.moveUp()).setDim(15, 15).setTooltip(new TextBuilder().translate("gui.recipe.moveup").build())); + sidebarButtons.add(new GuiButtonIcon("down", Icon.ARROW_DOWN, x -> tree.moveDown()).setDim(15, 15).setTooltip(new TextBuilder().translate("gui.recipe.movedown").build())); + sidebarButtons.add(new GuiButtonIcon("merge", Icon.MERGE, x -> OPEN_MERGE.open(new CompoundTag()).init(this)).setDim(15, 15).setTooltip(new TextBuilder().translate( + "gui.recipe.merge").build())); GuiParent topCenter = new GuiParent(GuiFlow.STACK_Y).setAlign(Align.STRETCH); top.add(topCenter.setDim(new GuiSizeRatioRules().widthRatio(0.4F).maxWidth(400)).setExpandableY()); diff --git a/src/main/java/team/creative/littletiles/common/ingredient/ColorIngredient.java b/src/main/java/team/creative/littletiles/common/ingredient/ColorIngredient.java index a76038b58..b35bb40c0 100644 --- a/src/main/java/team/creative/littletiles/common/ingredient/ColorIngredient.java +++ b/src/main/java/team/creative/littletiles/common/ingredient/ColorIngredient.java @@ -1,6 +1,7 @@ package team.creative.littletiles.common.ingredient; import net.minecraft.ChatFormatting; +import net.minecraft.util.Mth; import team.creative.creativecore.common.util.mc.LanguageUtils; import team.creative.creativecore.common.util.mc.TooltipUtils; import team.creative.creativecore.common.util.text.TextBuilder; @@ -109,7 +110,7 @@ public ColorIngredient add(ColorIngredient ingredient) { if (remaining == null) remaining = new ColorIngredient(); remaining.black = this.black - this.limitBlack; - this.black = limitBlack; + this.black = 0; } this.cyan += ingredient.cyan; @@ -117,7 +118,7 @@ public ColorIngredient add(ColorIngredient ingredient) { if (remaining == null) remaining = new ColorIngredient(); remaining.cyan = this.cyan - this.limitCyan; - this.cyan = limitCyan; + this.cyan = 0; } this.magenta += ingredient.magenta; if (this.limitMagenta >= 0 && this.magenta > limitMagenta) { @@ -161,14 +162,14 @@ public ColorIngredient sub(ColorIngredient ingredient) { if (remaining == null) remaining = new ColorIngredient(); remaining.magenta = -this.magenta; - this.magenta = limitMagenta; + this.magenta = 0; } this.yellow -= ingredient.yellow; if (this.yellow < 0) { if (remaining == null) remaining = new ColorIngredient(); remaining.yellow = -this.yellow; - this.yellow = limitYellow; + this.yellow = 0; } return remaining; } @@ -245,9 +246,9 @@ public void print(TextBuilder text) { message += (message.isEmpty() ? "" : " ") + getYellowDescription(); text.text(message); } - - public static float dyeToBlockPercentage = 4096; - public static final int BOTTLE_SIZE = (int) (dyeToBlockPercentage * 64); + + public static final double DYE_TO_BLOCK_PERCENTAGE = 4096; + public static final int BOTTLE_SIZE = (int) (DYE_TO_BLOCK_PERCENTAGE * 64); public static ColorIngredient getColors(LittleElement tile, double volume) { if (tile.hasColor()) { @@ -272,7 +273,7 @@ public static ColorIngredient getColors(LittleGrid grid, LittleTile tile) { } public static ColorIngredient getColors(int color) { - float cmyk_scale = dyeToBlockPercentage; + double cmyk_scale = DYE_TO_BLOCK_PERCENTAGE; int r = color >> 16 & 255; int g = color >> 8 & 255; @@ -290,7 +291,7 @@ public static ColorIngredient getColors(int color) { m = (m - min_cmy) / (1 - min_cmy); y = (y - min_cmy) / (1 - min_cmy); float k = min_cmy; - return new ColorIngredient((int) (k * cmyk_scale), (int) (c * cmyk_scale), (int) (m * cmyk_scale), (int) (y * cmyk_scale)); + return new ColorIngredient(Mth.ceil(k * cmyk_scale), Mth.ceil(c * cmyk_scale), Mth.ceil(m * cmyk_scale), Mth.ceil(y * cmyk_scale)); } } diff --git a/src/main/java/team/creative/littletiles/common/level/handler/LittleAnimationHandler.java b/src/main/java/team/creative/littletiles/common/level/handler/LittleAnimationHandler.java index ff89b7afd..2009249a5 100644 --- a/src/main/java/team/creative/littletiles/common/level/handler/LittleAnimationHandler.java +++ b/src/main/java/team/creative/littletiles/common/level/handler/LittleAnimationHandler.java @@ -119,7 +119,7 @@ public LittleHitResult getHit(Vec3 pos, Vec3 look, double reach) { if (tempResult == null || !(tempResult.hit instanceof BlockHitResult)) continue; double tempDistance = pos.distanceTo(entity.getOrigin().transformPointToWorld(tempResult.hit.getLocation())); - if (newHit == null || tempDistance < distance) { + if (tempDistance < distance) { newHit = tempResult; distance = tempDistance; } diff --git a/src/main/java/team/creative/littletiles/common/level/tick/LittleTicker.java b/src/main/java/team/creative/littletiles/common/level/tick/LittleTicker.java index 6be163253..6ecd23449 100644 --- a/src/main/java/team/creative/littletiles/common/level/tick/LittleTicker.java +++ b/src/main/java/team/creative/littletiles/common/level/tick/LittleTicker.java @@ -26,6 +26,7 @@ public class LittleTicker extends LevelHandler implements Iterable signalChanged = new ArrayList<>(); private boolean processingChanged = false; private List signalChangedSchedule = new ArrayList<>(); + private final boolean client; public int tick = Integer.MIN_VALUE; public int latest = Integer.MIN_VALUE; @@ -36,6 +37,7 @@ public class LittleTicker extends LevelHandler implements Iterable entry : updateStructures.object2BooleanEntrySet()) { - LittleStructure structure = entry.getKey(); - if (structure.mainBlock.isRemoved()) - continue; - LittleTiles.NETWORK.sendToClient(structure.generateUpdatePacket(entry.getBooleanValue()), structure.getStructureLevel(), structure.getStructurePos()); + + if (!client) { + if (!updateStructures.isEmpty()) { + synchronized (updateStructures) { + for (Entry entry : updateStructures.object2BooleanEntrySet()) { + LittleStructure structure = entry.getKey(); + if (structure.mainBlock.isRemoved()) + continue; + LittleTiles.NETWORK.sendToClient(structure.generateUpdatePacket(entry.getBooleanValue()), structure.getStructureLevel(), structure.getStructurePos()); + } + + updateStructures.clear(); } - - updateStructures.clear(); } - } - - if (!signalChanged.isEmpty()) { - synchronized (signalChanged) { - processingChanged = true; - for (ISignalSchedulable signal : signalChanged) - try { - signal.updateSignaling(); - } catch (CorruptedConnectionException | NotYetConnectedException e) {} - signalChanged.clear(); - processingChanged = false; - signalChanged.addAll(signalChangedSchedule); - signalChangedSchedule.clear(); + + if (!signalChanged.isEmpty()) { + synchronized (signalChanged) { + processingChanged = true; + for (ISignalSchedulable signal : signalChanged) + try { + signal.updateSignaling(); + } catch (CorruptedConnectionException | NotYetConnectedException e) {} + signalChanged.clear(); + processingChanged = false; + signalChanged.addAll(signalChangedSchedule); + signalChangedSchedule.clear(); + } } } } diff --git a/src/main/java/team/creative/littletiles/common/math/location/StructureLocation.java b/src/main/java/team/creative/littletiles/common/math/location/StructureLocation.java index 9798bd1ef..ef2fc19ca 100644 --- a/src/main/java/team/creative/littletiles/common/math/location/StructureLocation.java +++ b/src/main/java/team/creative/littletiles/common/math/location/StructureLocation.java @@ -80,4 +80,9 @@ public LittleStructure find(LevelAccessor level) throws LittleActionException { } else throw new LittleActionException.BlockEntityNotFoundException(); } + + @Override + public String toString() { + return levelUUID + ":" + pos.getX() + "," + pos.getY() + "," + pos.getZ() + "," + index; + } } diff --git a/src/main/java/team/creative/littletiles/common/placement/Placement.java b/src/main/java/team/creative/littletiles/common/placement/Placement.java index efcb06cdd..d8ae11eb5 100644 --- a/src/main/java/team/creative/littletiles/common/placement/Placement.java +++ b/src/main/java/team/creative/littletiles/common/placement/Placement.java @@ -193,14 +193,14 @@ public PlacementResult place() throws LittleActionException { List snaps = new ArrayList<>(); for (BlockPos snapPos : blocks.keySet()) snaps.add(BlockSnapshot.create(level.dimension(), level, snapPos)); - + EntityMultiPlaceEvent event = new BlockEvent.EntityMultiPlaceEvent(snaps, level.getBlockState(preview.position.facing == null ? preview.position .getPos() : preview.position.getPos().relative(preview.position.facing.toVanilla())), player); MinecraftForge.EVENT_BUS.post(event); if (event.isCanceled()) { for (BlockPos snapPos : blocks.keySet()) LittleAction.sendBlockResetToClient(level, player, snapPos); - return null; + throw new LittleTilesConfig.AreaProtected(); } } try { @@ -538,6 +538,7 @@ public void place(PlacementResult result) throws LittleActionException { if (preview.mode.placeTile(context, structure.getStructure(), tile) && playSounds && !soundsToBePlayed.contains(tile.getSound())) soundsToBePlayed.add(tile.getSound()); } catch (LittleActionException e) { + LittleTiles.LOGGER.catching(e); throw new RuntimeException(e); } } @@ -545,9 +546,10 @@ public void place(PlacementResult result) throws LittleActionException { }); }); } catch (RuntimeException e) { - if (e.getCause() instanceof LittleActionException) + if (e.getCause() instanceof LittleActionException) { + LittleTiles.LOGGER.catching(e); throw (LittleActionException) e.getCause(); - else + } else throw e; } } diff --git a/src/main/java/team/creative/littletiles/common/placement/selection/AreaSelectionMode.java b/src/main/java/team/creative/littletiles/common/placement/selection/AreaSelectionMode.java index f57b25308..48f526e66 100644 --- a/src/main/java/team/creative/littletiles/common/placement/selection/AreaSelectionMode.java +++ b/src/main/java/team/creative/littletiles/common/placement/selection/AreaSelectionMode.java @@ -123,7 +123,7 @@ else if (pos2 == null) AABB bb = new AABB(minX, minY, minZ, maxX + 1, maxY + 1, maxZ + 1); for (LittleEntity animation : LittleTiles.ANIMATION_HANDLERS.get(level).find(bb)) - search.scanLevel(level, animation.getOrigin().getOBB(bb)); + search.scanLevel(level, minX, minY, minZ, maxX, maxY, maxZ); return search.build(); } diff --git a/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapePillar.java b/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapePillar.java index 33be5829e..c81a236d6 100644 --- a/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapePillar.java +++ b/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapePillar.java @@ -92,16 +92,33 @@ protected void addBoxes(LittleBoxes boxes, ShapeSelection selection, boolean low Axis axis = box.getSize().getLongestAxis(); - Facing minFacing = originalMin.facing; - Facing maxFacing = originalMax.facing; - LittleVec originalMinVec = originalMin.getRelative(boxes.pos); LittleVec originalMaxVec = originalMax.getRelative(boxes.pos); + + boolean facingPositive = originalMinVec.get(axis) > originalMaxVec.get(axis); + + boolean simple = selection.getNBT().getBoolean("simple"); + + Facing startFacing = originalMin.facing; + Facing endFacing = originalMax.facing; + if (startFacing == null || endFacing == null) { + simple = true; + + if (originalMax.facing != null) + startFacing = originalMax.facing.opposite(); + else + startFacing = axis.facing(facingPositive); + if (endFacing == null) + endFacing = startFacing.opposite(); + } + + Facing minFacing = startFacing; + Facing maxFacing = endFacing; LittleBox minBox = new LittleBox(originalMinVec); LittleBox maxBox = new LittleBox(originalMaxVec); - if (selection.getNBT().getBoolean("simple")) { + if (simple) { minFacing = null; maxFacing = null; } else { @@ -120,16 +137,15 @@ protected void addBoxes(LittleBoxes boxes, ShapeSelection selection, boolean low axis = maxFacing.axis; CornerCache cache = box.new CornerCache(false); - - boolean facingPositive = originalMinVec.get(axis) > originalMaxVec.get(axis); + if (minFacing != null && minFacing == maxFacing) { minFacing = Facing.get(axis, originalMinVec.get(axis) > originalMaxVec.get(axis)); maxFacing = minFacing.opposite(); } - - minBox.growAway(thickness, originalMin.facing); - maxBox.growAway(thickness, originalMax.facing); + + minBox.growAway(thickness, startFacing); + maxBox.growAway(thickness, endFacing); box.growToInclude(minBox); box.growToInclude(maxBox); diff --git a/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeSelectable.java b/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeSelectable.java index 0bbee6fcb..af831375e 100644 --- a/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeSelectable.java +++ b/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeSelectable.java @@ -48,7 +48,7 @@ public void addBox(LittleBoxes boxes, boolean inside, LittleGrid grid, BlockPos if (inside) boxes.addBox(grid, pos, box); - else { + else if (facing != null) { if (facing.positive) box.setMax(facing.axis, 1); else diff --git a/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeWall.java b/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeWall.java index 546165c1b..32da3d8fe 100644 --- a/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeWall.java +++ b/src/main/java/team/creative/littletiles/common/placement/shape/type/LittleShapeWall.java @@ -39,15 +39,28 @@ protected void addBoxes(LittleBoxes boxes, ShapeSelection selection, boolean low originalMin.convertTo(boxes.getGrid()); originalMax.convertTo(boxes.getGrid()); - int thickness = Math.max(0, selection.getNBT().getInt("thickness") - 1); + LittleTransformableBox box = new LittleTransformableBox(selection.getOverallBox(), new int[1]); Axis toIgnore = direction == 0 ? Axis.Y : direction == 1 ? Axis.X : Axis.Z; Axis oneIgnore = toIgnore.one(); Axis twoIgnore = toIgnore.two(); Axis axis = box.getSize(oneIgnore) > box.getSize(twoIgnore) ? oneIgnore : twoIgnore; - Facing minFacing = originalMin.facing; - Facing maxFacing = originalMax.facing; + LittleVec originalMinVec = originalMin.getRelative(boxes.pos); + LittleVec originalMaxVec = originalMax.getRelative(boxes.pos); + boolean facingPositive = originalMinVec.get(axis) > originalMaxVec.get(axis); + + Facing startFacing = originalMin.facing; + if (startFacing == null) + startFacing = axis.facing(facingPositive); + Facing endFacing = originalMax.facing; + if (endFacing == null) + endFacing = axis.facing(!facingPositive); + + int thickness = Math.max(0, selection.getNBT().getInt("thickness") - 1); + + Facing minFacing = startFacing; + Facing maxFacing = endFacing; if (minFacing.axis == toIgnore || box.getSize(minFacing.axis) == 1) minFacing = null; @@ -58,8 +71,6 @@ protected void addBoxes(LittleBoxes boxes, ShapeSelection selection, boolean low axis = minFacing.axis; CornerCache cache = box.new CornerCache(false); - LittleVec originalMinVec = originalMin.getRelative(boxes.pos); - LittleVec originalMaxVec = originalMax.getRelative(boxes.pos); LittleBox minBox = new LittleBox(originalMinVec); LittleBox maxBox = new LittleBox(originalMaxVec); @@ -68,9 +79,9 @@ protected void addBoxes(LittleBoxes boxes, ShapeSelection selection, boolean low minFacing = Facing.get(axis, originalMinVec.get(axis) > originalMaxVec.get(axis)); maxFacing = minFacing.opposite(); } - - minBox.growAway(thickness, originalMin.facing); - maxBox.growAway(thickness, originalMax.facing); + + minBox.growAway(thickness, startFacing); + maxBox.growAway(thickness, endFacing); box.growToInclude(minBox); box.growToInclude(maxBox); @@ -80,8 +91,6 @@ protected void addBoxes(LittleBoxes boxes, ShapeSelection selection, boolean low minBox.setMax(toIgnore, box.getMax(toIgnore)); maxBox.setMax(toIgnore, box.getMax(toIgnore)); - boolean facingPositive = originalMinVec.get(axis) > originalMaxVec.get(axis); - LittleShapePillar.setStartAndEndBox(cache, axis.facing(facingPositive), minFacing, maxFacing, minBox, maxBox, selection.inside); box.setData(cache.getData()); diff --git a/src/main/java/team/creative/littletiles/common/structure/LittleStructure.java b/src/main/java/team/creative/littletiles/common/structure/LittleStructure.java index 10e756d37..d3cdf4028 100644 --- a/src/main/java/team/creative/littletiles/common/structure/LittleStructure.java +++ b/src/main/java/team/creative/littletiles/common/structure/LittleStructure.java @@ -172,7 +172,7 @@ public void checkConnections() throws CorruptedConnectionException, NotYetConnec throw new RemovedStructureException(); for (StructureBlockConnector block : blocks) - block.connect(); + block.checkConnection(); try { if (hasParent()) @@ -183,7 +183,7 @@ public void checkConnections() throws CorruptedConnectionException, NotYetConnec for (StructureChildConnection child : children.all()) try { - child.getStructure().checkConnections(); + child.getStructureUncached().checkConnections(); } catch (CorruptedConnectionException e) { throw new MissingChildException(child, e); } @@ -537,9 +537,9 @@ public void removeStructure(LittleUpdateCollector neighbor) throws CorruptedConn } mainBlock.getBE().updateTilesSecretly((x) -> x.removeStructure(getIndex())); } - - public void removeStructureSameLevel(LittleUpdateCollector neighbor) throws CorruptedConnectionException, NotYetConnectedException { - checkConnections(); + + public void removeStructureSameLevelWithoutCheck(LittleUpdateCollector neighbor) throws CorruptedConnectionException, NotYetConnectedException { + //checkConnections(); structureDestroyed(); for (StructureChildConnection child : children.all()) @@ -585,6 +585,10 @@ public LittleAnimationEntity getAnimationEntity() { public StructureAbsolute createAnimationCenter(BlockPos pos, LittleGrid grid) { return null; } + + public boolean playSoundWhenChangingState() { + return true; + } /** Called before structure is removed. New structure already exists. Can be used to transfer information, that are not saved or loaded. * @@ -604,7 +608,7 @@ public LittleAnimationEntity changeToEntityForm() throws LittleActionException { LittleAnimationLevel subLevel = new LittleAnimationLevel(level); BlockPos pos = getStructurePos(); - Placement placement = new Placement(null, subLevel, PlacementPreview.load(null, PlacementMode.ALL, getAbsolutePreviewsSameLevelOnly(pos), Facing.EAST)); + Placement placement = new Placement(null, subLevel, PlacementPreview.load(null, PlacementMode.ALL, getAbsolutePreviewsSameLevelOnly(pos), Facing.EAST)).setPlaySounds(playSoundWhenChangingState()); LittleUpdateCollector collector = new LittleUpdateCollector(); LittleAnimationEntity entity = new LittleAnimationEntity(level, subLevel, createAnimationCenter(mainBlock.getPos(), mainBlock.getGrid()), placement); @@ -614,8 +618,8 @@ public LittleAnimationEntity changeToEntityForm() throws LittleActionException { LittleTiles.NETWORK.sendToClientTracking(new StructureBlockToEntityPacket(location, entity), entity); transferOverFormChange(entity.getStructure()); - - removeStructureSameLevel(collector); + + removeStructureSameLevelWithoutCheck(collector); entity.getStructure().transferChildrenToAnimation(entity); collector.process(); @@ -644,7 +648,7 @@ public void changeToBlockForm() throws LittleActionException { Level level = entity.level(); BlockPos pos = getStructurePos(); - Placement placement = new Placement(null, level, PlacementPreview.load(null, PlacementMode.ALL, getAbsolutePreviewsSameLevelOnly(pos), Facing.EAST)); + Placement placement = new Placement(null, level, PlacementPreview.load(null, PlacementMode.ALL, getAbsolutePreviewsSameLevelOnly(pos), Facing.EAST)).setPlaySounds(playSoundWhenChangingState()); LittleUpdateCollector collector = new LittleUpdateCollector(); PlacementResult result = placement.place(); @@ -657,8 +661,8 @@ public void changeToBlockForm() throws LittleActionException { LittleTiles.NETWORK.sendToClientTracking(new StructureEntityToBlockPacket(entity), entity); transferOverFormChange(result.parentStructure); - - removeStructureSameLevel(collector); + + removeStructureSameLevelWithoutCheck(collector); collector.process(); entity.setRemoved(RemovalReason.KILLED); @@ -819,6 +823,8 @@ public int internalOutputCount() { } public SignalExternalOutputHandler getExternalOutput(int index) { + if (externalHandler == null) + return null; return externalHandler.get(index); } diff --git a/src/main/java/team/creative/littletiles/common/structure/animation/AnimationTimeline.java b/src/main/java/team/creative/littletiles/common/structure/animation/AnimationTimeline.java index ac71f947f..742fecb45 100644 --- a/src/main/java/team/creative/littletiles/common/structure/animation/AnimationTimeline.java +++ b/src/main/java/team/creative/littletiles/common/structure/animation/AnimationTimeline.java @@ -65,7 +65,12 @@ public AnimationTimeline(int duration, List events) { Collections.sort(tempList); this.events = new MarkList<>(tempList); } - + + public boolean isAligned() { + return offX == ValueCurve.ONE_EMPTY && offY == ValueCurve.ONE_EMPTY && offZ == ValueCurve.ONE_EMPTY && rotX == ValueCurve.ONE_EMPTY && rotY == ValueCurve.ONE_EMPTY && rotZ == ValueCurve.ONE_EMPTY; + } + + public ValueCurve get(PhysicalPart part) { return switch (part) { case OFFX -> offX; @@ -236,7 +241,12 @@ public void reverse(AnimationContext context) { public Iterable allEvents() { return events.allIgnoreMark(); } - + + public int getTick() { + return tick; + } + + public static class AnimationEventEntry implements Comparable { private AnimationEvent event; diff --git a/src/main/java/team/creative/littletiles/common/structure/connection/IStructureConnection.java b/src/main/java/team/creative/littletiles/common/structure/connection/IStructureConnection.java index 4e41a0c08..6914bc458 100644 --- a/src/main/java/team/creative/littletiles/common/structure/connection/IStructureConnection.java +++ b/src/main/java/team/creative/littletiles/common/structure/connection/IStructureConnection.java @@ -8,6 +8,8 @@ public interface IStructureConnection { public BlockPos getStructurePosition(); + + public LittleStructure getStructureUncached() throws CorruptedConnectionException, NotYetConnectedException; public LittleStructure getStructure() throws CorruptedConnectionException, NotYetConnectedException; diff --git a/src/main/java/team/creative/littletiles/common/structure/connection/block/StructureBlockConnector.java b/src/main/java/team/creative/littletiles/common/structure/connection/block/StructureBlockConnector.java index e276bfdf4..575014b9d 100644 --- a/src/main/java/team/creative/littletiles/common/structure/connection/block/StructureBlockConnector.java +++ b/src/main/java/team/creative/littletiles/common/structure/connection/block/StructureBlockConnector.java @@ -50,8 +50,9 @@ public BETiles getBlockEntity() throws CorruptedConnectionException, NotYetConne } else throw new NotYetConnectedException(); } - - public void connect() throws CorruptedConnectionException, NotYetConnectedException { + + public void checkConnection() throws CorruptedConnectionException, NotYetConnectedException { + cachedBE = null; BETiles be = getBlockEntity(); if (!be.hasLoaded()) throw new NotYetConnectedException(); diff --git a/src/main/java/team/creative/littletiles/common/structure/connection/children/StructureChildConnection.java b/src/main/java/team/creative/littletiles/common/structure/connection/children/StructureChildConnection.java index a1861d405..f6ffa162b 100644 --- a/src/main/java/team/creative/littletiles/common/structure/connection/children/StructureChildConnection.java +++ b/src/main/java/team/creative/littletiles/common/structure/connection/children/StructureChildConnection.java @@ -81,13 +81,20 @@ public void destroyStructure(LittleUpdateCollector neighbor) throws CorruptedCon public void destroyStructureSameLevel(LittleUpdateCollector neighbor) throws CorruptedConnectionException, NotYetConnectedException { if (!isChild()) - getStructure().removeStructureSameLevel(neighbor); + getStructure().removeStructureSameLevelWithoutCheck(neighbor); } public LittleEntity getAnimation() { return null; } - + + @Override + public LittleStructure getStructureUncached() throws CorruptedConnectionException, NotYetConnectedException { + cachedBE = null; + return getStructure(); + } + + @Override public BlockPos getStructurePosition() { return relativePos.offset(parent.getStructurePos()); diff --git a/src/main/java/team/creative/littletiles/common/structure/connection/direct/StructureConnection.java b/src/main/java/team/creative/littletiles/common/structure/connection/direct/StructureConnection.java index c2eb22db8..f4af17be5 100644 --- a/src/main/java/team/creative/littletiles/common/structure/connection/direct/StructureConnection.java +++ b/src/main/java/team/creative/littletiles/common/structure/connection/direct/StructureConnection.java @@ -81,7 +81,14 @@ protected BETiles getBlockEntity() throws CorruptedConnectionException, NotYetCo } else throw new NotYetConnectedException(); } - + + @Override + public LittleStructure getStructureUncached() throws CorruptedConnectionException, NotYetConnectedException { + cachedBE = null; + return getStructure(); + } + + @Override public LittleStructure getStructure() throws CorruptedConnectionException, NotYetConnectedException { BETiles be = getBlockEntity(); diff --git a/src/main/java/team/creative/littletiles/common/structure/registry/gui/LittleDoorAxisGui.java b/src/main/java/team/creative/littletiles/common/structure/registry/gui/LittleDoorAxisGui.java index ab79dda04..7aa6e760d 100644 --- a/src/main/java/team/creative/littletiles/common/structure/registry/gui/LittleDoorAxisGui.java +++ b/src/main/java/team/creative/littletiles/common/structure/registry/gui/LittleDoorAxisGui.java @@ -58,7 +58,7 @@ protected void createSpecific(LittleDoor door) { viewer.setView(Facing.get(axis, true)); GuiTabsMapped> tabs = new GuiTabsMapped<>("tabs"); tabs.createTab(x -> new LittleAxisDoorRotationDirection(viewer.axis(), x.get("direction", GuiStateButton.class).getState() == 0), Component.translatable( - "gui.door.rotation.direction")).add(new GuiStateButton("direction", rotation instanceof LittleAxisDoorRotationDirection d && !d.clockwise ? 1 : 0, translate( + "gui.door.rotation.direction")).add(new GuiStateButton("direction", rotation instanceof LittleAxisDoorRotationDirection d && d.clockwise ? 1 : 0, translate( "gui.clockwise"), translate("gui.counterclockwise"))); GuiTextfield angle = new GuiTextfield("angle").setFloatOnly(); diff --git a/src/main/java/team/creative/littletiles/common/structure/signal/logic/SignalMode.java b/src/main/java/team/creative/littletiles/common/structure/signal/logic/SignalMode.java index c597eb5ed..d626021b9 100644 --- a/src/main/java/team/creative/littletiles/common/structure/signal/logic/SignalMode.java +++ b/src/main/java/team/creative/littletiles/common/structure/signal/logic/SignalMode.java @@ -6,6 +6,7 @@ import net.minecraft.nbt.IntArrayTag; import net.minecraft.nbt.ListTag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import team.creative.creativecore.common.gui.GuiParent; @@ -607,7 +608,10 @@ public GuiSignalModeConfiguration(int delay) { public abstract GuiSignalModeConfiguration copy(); public abstract SignalOutputHandler getHandler(ISignalComponent component, LittleStructure structure); - + + public MutableComponent description(int configuredDelay) { + return Component.translatable(getMode().translateKey).append(" ").append(Component.translatable("gui.delay")).append(": " + configuredDelay); + } } @OnlyIn(Dist.CLIENT) @@ -702,7 +706,11 @@ public SignalOutputHandler getHandler(ISignalComponent component, LittleStructur nbt.putInt("length", length); return getMode().create(component, delay, nbt, false); } - + + @Override + public MutableComponent description(int configuredDelay) { + return super.description(configuredDelay).append(" ").append(Component.translatable("gui.signal.length").append(": " + length)); + } } @OnlyIn(Dist.CLIENT) @@ -737,7 +745,12 @@ public SignalOutputHandler getHandler(ISignalComponent component, LittleStructur nbt.putInt("length", length); return getMode().create(component, delay, nbt, false); } - + + @Override + public MutableComponent description(int configuredDelay) { + return super.description(configuredDelay).append(" ").append(Component.translatable("gui.signal.length").append(": " + length)); + } + } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/team/creative/littletiles/common/structure/signal/network/SignalNetwork.java b/src/main/java/team/creative/littletiles/common/structure/signal/network/SignalNetwork.java index 8fc80cade..1a020ee24 100644 --- a/src/main/java/team/creative/littletiles/common/structure/signal/network/SignalNetwork.java +++ b/src/main/java/team/creative/littletiles/common/structure/signal/network/SignalNetwork.java @@ -43,7 +43,7 @@ public boolean requiresResearch() { public void notifyChange() { if (!forceUpdate) { SignalState oldState = SignalState.copy(state); - state.reset(); + state = state.reset(); for (int i = 0; i < outputs.size(); i++) try { diff --git a/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleDoor.java b/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleDoor.java index 7f7b5a967..1a3d21381 100644 --- a/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleDoor.java +++ b/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleDoor.java @@ -135,7 +135,12 @@ public void toggleState() { if (activateParent) startTransitionIfNecessary(output.getState().number()); } - + + @Override + public boolean playSoundWhenChangingState() { + return playPlaceSounds; + } + public static class LittleDoorType extends LittleStateStructureType { public LittleDoorType(String id, Class structureClass, BiFunction factory, LittleAttributeBuilder attribute) { diff --git a/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleStateStructure.java b/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleStateStructure.java index 420a55597..de14d92c9 100644 --- a/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleStateStructure.java +++ b/src/main/java/team/creative/littletiles/common/structure/type/animation/LittleStateStructure.java @@ -94,16 +94,16 @@ protected boolean startTransition(int start, int end, @Nullable AnimationTimelin try { LittleStateStructure structure = this; - if ((!states.get(end).isAligned() || !states.get(start).equals(states.get(end))) && !isAnimated()) + if ((!states.get(end).isAligned() || !states.get(start).equals(states.get(end)) || !timeline.isAligned()) && !isAnimated()) structure = (LittleStateStructure) changeToEntityForm().getStructure(); structure.aimedState = end; structure.timeline = timeline; structure.timeline.start(states.get(start), states.get(end), this::createEmptyCurve); structure.physical = new PhysicalState(); - - LittleTiles.NETWORK.sendToClient(new StructureStartAnimationPacket(structure.getStructureLocation(), structure.timeline), structure.getStructureLevel(), structure - .getStructurePos()); + + LittleTiles.NETWORK.sendToClient(new StructureStartAnimationPacket(structure.getStructureLocation(), structure.timeline.copy()), structure.getStructureLevel(), + structure.getStructurePos()); // Needs to send a copy, because before the packet is send the timeline might have ticked already, causing skipped ticks on client side structure.queueForNextTick(); return true; @@ -309,7 +309,11 @@ public void play(SoundEvent event, float volume, float pitch) { @OnlyIn(Dist.CLIENT) private void playClient(SoundEvent event, float volume, float pitch) { - GuiControl.playSound(new EntitySound(event, getAnimationEntity(), volume, pitch, SoundSource.BLOCKS)); + var entity = getAnimationEntity(); + if (entity != null) + GuiControl.playSound(new EntitySound(event, getAnimationEntity(), volume, pitch, SoundSource.BLOCKS)); + else + getStructureLevel().playLocalSound(getStructurePos(), event, SoundSource.BLOCKS, volume, pitch, false); } @Override diff --git a/src/main/java/team/creative/littletiles/common/structure/type/premade/signal/LittleSignalCableBase.java b/src/main/java/team/creative/littletiles/common/structure/type/premade/signal/LittleSignalCableBase.java index 2b4db3d37..7d4a3e12e 100644 --- a/src/main/java/team/creative/littletiles/common/structure/type/premade/signal/LittleSignalCableBase.java +++ b/src/main/java/team/creative/littletiles/common/structure/type/premade/signal/LittleSignalCableBase.java @@ -495,7 +495,8 @@ public void structureDestroyed() { if (faces[i] != null) { ISignalStructureBase connection = faces[i].connection; faces[i].disconnect(getFacing(i)); - connection.findNetwork(); + if (connection != null) + connection.findNetwork(); } } } diff --git a/src/main/resources/assets/littletiles/blockstates/arrow_output.json b/src/main/resources/assets/littletiles/blockstates/arrow_output.json index 1339aed67..b53ef9b9a 100644 --- a/src/main/resources/assets/littletiles/blockstates/arrow_output.json +++ b/src/main/resources/assets/littletiles/blockstates/arrow_output.json @@ -5,7 +5,8 @@ }, "facing=south": { "model": "littletiles:block/output_arrow_up", - "x": 90 + "x": 90, + "y": 180 }, "facing=east": { "model": "littletiles:block/output_arrow_up", @@ -17,7 +18,8 @@ }, "facing=north": { "model": "littletiles:block/output_arrow_down", - "x": 90 + "x": 90, + "y": 180 }, "facing=west": { "model": "littletiles:block/output_arrow_down", diff --git a/src/main/resources/assets/littletiles/lang/en_us.json b/src/main/resources/assets/littletiles/lang/en_us.json index 3dbf07d1e..996d461c0 100644 --- a/src/main/resources/assets/littletiles/lang/en_us.json +++ b/src/main/resources/assets/littletiles/lang/en_us.json @@ -76,6 +76,8 @@ "gui.structure_builder.craft": "craft", "gui.structure_builder.failed": "\u00A7cfailed", "gui.signal.events": "Signal Outputs", + "gui.signal.equation": "Equation", + "gui.signal.bandwidth": "Bandwidth", "gui.distance.blocks": "block distance", "gui.distance.pixels": "pixel distance", "gui.recipe.dialog.clear": "Do you really want to clear all content?", @@ -381,6 +383,7 @@ "structure.clock_sensor16": "Precise Clock Sensor (16 bit)", "structure.description.clock_sensor16": "Outputs the time of the day from 0 to 24000.\nHas a 16 bit output.", "gui.signal.components": "Components", + "gui.signal.out": "out", "gui.signal.configuration.result": "result:", "gui.signal.configuration.addop": "+", "gui.signal.configuration.add": "+", diff --git a/src/main/resources/assets/littletiles/lang/zh_cn.json b/src/main/resources/assets/littletiles/lang/zh_cn.json new file mode 100644 index 000000000..5d52cbcc7 --- /dev/null +++ b/src/main/resources/assets/littletiles/lang/zh_cn.json @@ -0,0 +1,410 @@ +{ + "gui.shape": "形状", + "gui.type": "类型", + "gui.hollow": "空心", + "gui.solid": "固体", + "gui.thickness": "厚度", + "gui.pixel.length": "像素", + "gui.interpolation": "插值方式", + "gui.interpolation.hermite": "hermite", + "gui.interpolation.cubic": "贝塞尔", + "gui.interpolation.linear": "线性", + "gui.interpolation.cosine": "三角", + "gui.axis.x": "x", + "gui.axis.y": "y", + "gui.axis.z": "z", + "gui.direction.east": "东", + "gui.direction.west": "西", + "gui.direction.up": "上", + "gui.direction.down": "下", + "gui.direction.south": "南", + "gui.direction.north": "北", + "gui.facing": "朝向", + "gui.box.transformable.second": "second-type", + "gui.true": "是", + "gui.false": "否", + "gui.click.left": "左键点击", + "gui.click.right": "右键点击", + "gui.paste": "粘贴", + "gui.import": "导入", + "gui.blocks": "方块", + "gui.tile.count": "块", + "gui.box.count": "boxes", + "gui.grid": "网格", + "gui.structure": "结构", + "gui.any": "任何", + "gui.export.data": "数据", + "gui.remove": "移除", + "gui.more": "更多", + "gui.replace_with": "替换为", + "gui.colorize": "着色", + "gui.undo": "撤回", + "gui.redo": "重做", + "gui.run": "运行", + "gui.plus": "+", + "gui.minus": "-", + "gui.previous": "<<", + "gui.next": ">>", + "gui.components": "组件", + "gui.edit": "编辑", + "gui.reset": "重置", + "gui.delay": "延时", + "gui.copy": "复制", + "gui.clear": "清除", + "gui.okay": "完成", + "gui.reload": "重载", + "gui.sort": "排序", + "gui.points.east": "右", + "gui.points.west": "左", + "gui.points.up": "上", + "gui.points.down": "下", + "gui.points.south": "近", + "gui.points.north": "远", + "gui.duration": "持续时间", + "gui.stay_animated": "保持实体", + "gui.no_clip": "穿透", + "gui.rightclick": "右键点击", + "gui.clockwise": "顺时针", + "gui.counterclockwise": "逆时针", + "gui.craft": "合成", + "gui.simple": "Simple", + "gui.color.rightclick": "right click to drain", + "gui.second_type": "second type", + "gui.structure_builder.width": "宽度", + "gui.structure_builder.height": "高度", + "gui.structure_builder.thickness": "厚度", + "gui.structure_builder.craft": "合成", + "gui.structure_builder.failed": "\u00A7c失败", + "gui.signal.events": "信号输出", + "gui.signal.equation": "Equation", + "gui.signal.bandwidth": "Bandwidth", + "gui.distance.blocks": "方块距离", + "gui.distance.pixels": "像素距离", + "gui.recipe.dialog.clear": "你真的要清除所有内容吗?", + "gui.recipe.dialog.delete": "你真的要删除 %s 吗?", + "gui.recipe.add": "添加", + "gui.recipe.duplicate": "复制", + "gui.recipe.delete": "删除", + "gui.recipe.moveup": "上移", + "gui.recipe.movedown": "下移", + "gui.recipe.merge": "合并2个结构", + "gui.recipe.move": "移动结构", + "gui.recipe.perspective": "更改透视模式", + "gui.recipe.home": "重载视图", + "gui.recipe.play": "播放", + "gui.recipe.pause": "暂停", + "gui.recipe.stop": "重置", + "gui.recipe.view.filter": "过滤渲染内容", + "gui.recipe.view.highlight": "高亮已选内容", + "gui.recipe.move.mode.default": "移动已选内容", + "gui.recipe.move.mode.checkbox": "Move checked", + "gui.recipe.merge.title": "将 \u00A7e 和 %s\u00A7r 合并为:", + "gui.recipe.merge.not_found": "Nothing found", + "gui.recipe.dialog.merge.failed": "无法合并结构。 \u00A7e%s\u00A7r 是 \u00A7e%s\u00A7r 的父级", + "gui.recipe.structure.name": "名称:", + "gui.recipe.cancel.dialog": "是否在关闭前保存图纸? 若否则任何修改将全部丢失!", + "gui.recipe.cancel.dialog.failed": "确定不保存图纸直接关闭?", + "gui.recipe.clear": "移除所有结构", + "gui.recipe.selection": "清除内容", + "gui.recipe.test": "检查", + "gui.recipe.test.recheck": "刷新测试", + "gui.recipe.solve": "溶解", + "gui.recipe.test.error.single": "1 个错误", + "gui.recipe.test.error.multiple": "%s 个错误", + "gui.recipe.test.result.fail": "\u00A7c测试失败", + "gui.recipe.test.result.success": "\u00A72测试通过", + "gui.recipe.test.overlap": "测试重复", + "gui.recipe.test.overlap.self.title": "Overlapping tiles in \u00A7e%s", + "gui.recipe.test.overlap.title": "Overlapping tiles between \u00A7e%s\u00A7r and \u00A7e%s", + "gui.recipe.test.overlap.tooltip": "Overlaps with \u00A7e%s", + "gui.recipe.test.overlap.desc.large": "\u00A7e%s\u00A7r blocks overlap", + "gui.recipe.test.overlap.desc.small": "\u00A7e%s\u00A7r tiles overlap (grid \u00A72%s\u00A7r)", + "gui.recipe.test.overlap.fix": "修复", + "gui.recipe.test.overlap.remove": "Remove area from:", + "gui.recipe.test.overlap.move": "移动结构", + "gui.recipe.test.signal.title": "Invalid signal equation for \u00A7e%s", + "gui.recipe.test.signal.desc": "无法找到 \u00A72%s", + "gui.recipe.storage.invisible": "隐藏的存储块", + "gui.door.play_place_sound": "播放放置音效", + "gui.door.stay_animated.tooltip": "如果可能的话,是否将门恢复为块.", + "gui.door.rightclick.tooltip": "是否可以通过右键打开或关闭.", + "gui.door.no_clip.tooltip": "其他物体能否与门的实体发生碰撞.", + "gui.door.play_place_sound.tooltip": "当门转化为实体或变回块形式时,它会放置所有的块.\n是否应该播放放置音效.", + "gui.door.distance": "距离", + "gui.door.direction": "方向", + "gui.door.rotation.direction": "方向", + "gui.door.rotation.angle": "角度", + "gui.door.axis.even": "奇数对齐", + "gui.door.closing": "关闭中...", + "gui.door.opening": "开启中...", + "gui.door.closed": "已关闭", + "gui.door.opened": "已开启", + "gui.door.offx": "offX", + "gui.door.offy": "offY", + "gui.door.offz": "offZ", + "gui.door.rotx": "rotX", + "gui.door.roty": "rotY", + "gui.door.rotz": "rotZ", + "gui.door.direction.both": "Both", + "gui.door.direction.opening": "开启", + "gui.door.direction.closing": "关闭", + "gui.door.sound": "音效", + "gui.door.sound.add": "+ 音效", + "gui.door.child": "子级", + "gui.door.clean.channel": "清除", + "gui.door.same_transition": "相同的过渡效果", + "gui.door.different_transition": "不同的过渡效果", + "gui.message.rightclick": "右键以显示信息", + "gui.message.status": "使用状态栏 (否则只在聊天框显示)", + "gui.error.invalid_grid": "无效的网格尺寸 \u00A72%s ...", + "gui.error.convert.structure": "无法替换 %s ...", + "gui.error.unknown": "未知错误: %s ...", + "gui.particle.count": "数量", + "gui.particle.per": "每", + "gui.particle.tick": "刻", + "gui.particle.size": "尺寸", + "gui.particle.preset": "预设", + "gui.particle.texture": "材质", + "gui.particle.collision": "碰撞", + "gui.particle.gravity": "重力", + "gui.particle.sizedeviation": "偏移", + "gui.particle.randomcolor": "随机颜色", + "gui.particle.age": "持续时长", + "gui.particle.agedeviation": "偏移", + "gui.particle.spread.random": "随机", + "gui.particle.spread.circular": "圆形", + "gui.particle.spread.speedx": "X-Side", + "gui.particle.spread.speedy": "速度", + "gui.particle.spread.speedz": "Z-Side", + "gui.particle.spread.radius": "半径", + "gui.particle.spread.spread": "偏移", + "gui.particle.spread.steps": "Steps", + "gui.particle.load": "加载预设", + "gui.particle.preset.smoke": "烟雾", + "gui.particle.preset.flame": "火焰", + "gui.particle.preset.water_drop": "水滴", + "gui.particle.preset.note": "音符", + "gui.particle.preset.big_smoke": "浓烟", + "gui.particle.preset.sand": "沙粒", + "gui.particle.preset.confetti": "彩纸屑", + "gui.blancomatic.craft": "合成", + "gui.blancomatic.cost": "消耗", + "dialog.screwdriver.no_task": "未选择任务", + "dialog.screwdriver.invalid_replacement": "无法替换方块", + "markmode.gui.allowlowresolution": "启用低分辨率模式", + "selection.include.vanilla": "包含原版方块", + "selection.include.cb": "C&B Blocks", + "selection.include.lt": "LittleTiles Blocks", + "selection.include.structure": "记住结构", + "selection.scale": "缩放", + "selection.no_tiles": "父级结构需要包含至少一个块!\n请禁用记住结构或修改您的选区.", + "mode.selection.area": "选区", + "selection.mode.area.pos.first": "选区第一个方块位置: %s %s %s", + "selection.mode.area.pos.second": "选区第二个方块位置: %s %s %s", + "selection.clear": "清除", + "gui.noclip.slowness": "Slowness (codweb)", + "creative_tab.littletiles": "LittleTiles", + "item.littletiles.hammer": "锤子", + "item.littletiles.multi_tiles": "Little Structure", + "item.littletiles.name": "配方图纸", + "item.littletiles.saw": "锯子", + "item.littletiles.bag": "收纳袋", + "item.littletiles.wrench": "扳手", + "item.littletiles.chisel": "凿子", + "item.littletiles.screwdriver": "螺丝刀", + "item.littletiles.paint_brush": "画笔", + "item.littletiles.glove": "手套", + "item.littletiles.blueprint": "蓝图", + "item.littletiles.bottle_black": "瓶装染料(黑色)", + "item.littletiles.bottle_cyan": "瓶装染料(青色)", + "item.littletiles.bottle_magenta": "瓶装染料(品红色)", + "item.littletiles.bottle_yellow": "瓶装染料(黄色)", + "gui.tooltip.arrow_keys": "方向键", + "littletiles.chisel.tooltip": "%s\n'%s' to pick block\nHold 'CTRL' to place more points\n'%s' to mark the position\n'%s' to rotate shape\n%s' to configure tool", + "littletiles.glove.tooltip": "%s\n'%s' to configure tool\n", + "littletiles.hammer.tooltip": "%s\nHold 'CTRL' to place more points\n'%s' to mark the position\n'%s' to rotate shape\n'%s' to configure tool\n", + "littletiles.paint_brush.tooltip": "%s\n'%s' to pick color\nHold 'CTRL' to place more points\n'%s' to mark the position\n'%s' to configure tool\n", + "littletiles.blueprint.selection.tooltip": "'%s' first position\n'%s' second position\n'%s' pick shape/ structure\n'%s' confirm/ configure selection\n", + "littletiles.tiles.tooltip": "'%s' configure options\n'%s' to rotate and '%s' to mirror", + "littletiles.saw.tooltip": "'%s' extend tile\n'%s' shrink tile\nHold 'CTRL' to go further", + "littletiles.screwdriver.tooltip": "'%s' first position\n'%s' second position\n'%s' modify selected area", + "block.littletiles.colored_clean": "染色方块(清澈)", + "block.littletiles.colored_floor": "染色方块(基底)", + "block.littletiles.colored_grainy_big": "染色方块(大纹理)", + "block.littletiles.colored_grainy": "染色方块(正常纹理)", + "block.littletiles.colored_grainy_low": "染色方块(低纹理)", + "block.littletiles.colored_brick": "染色方块(砖块)", + "block.littletiles.colored_bordered": "染色方块(邻接)", + "block.littletiles.colored_brick_big": "染色方块(大石砖)", + "block.littletiles.colored_chiseled": "染色方块(錾制石砖)", + "block.littletiles.colored_broken_brick_big": "染色方块(大裂石砖)", + "block.littletiles.colored_clay": "染色方块(黏土)", + "block.littletiles.colored_strips": "染色方块(木板)", + "block.littletiles.colored_lava": "岩浆方块", + "block.littletiles.colored_white_lava": "岩浆方块(白色)", + "block.littletiles.colored_gravel": "染色方块(砾石)", + "block.littletiles.colored_sand": "染色方块(砂纹)", + "block.littletiles.colored_stone": "染色方块(石纹)", + "block.littletiles.colored_cork": "染色方块(石纹)", + "block.littletiles.colored_water": "水方块", + "block.littletiles.storage": "存储方块", + "block.littletiles.signal_converter": "信号转换器", + "key.categories.littletiles": "LittleTiles 设置", + "key.little.mirror": "镜像预览", + "key.little.mark": "微调预览", + "key.little.config.item": "工具设置", + "key.rotatedown": "向下旋转", + "key.rotateleft": "向左旋转", + "key.rotateright": "向右旋转", + "key.rotateup": "向上旋转", + "key.little.redo": "重做", + "key.little.undo": "撤回", + "action.tile.notthere": "块丢失", + "action.tile.notfound": "未找到块结构", + "action.blockentity.notfound": "未找到方块实体", + "action.entity.notfound": "未找到实体", + "action.structure.notloaded": "结构尚未加载", + "action.revert.notavailable": "操作无法撤销", + "color.unit.black": "黑色", + "color.unit.cyan": "青色", + "color.unit.magenta": "品红色", + "color.unit.yellow": "黄色", + "color.unit.single": "unit", + "color.unit.multiple": "units", + "volume.unit.big.single": "block", + "volume.unit.big.multiple": "blocks", + "volume.unit.big.short": "b", + "volume.unit.small.single": "pixel", + "volume.unit.small.multiple": "pixels", + "volume.unit.small.short": "p", + "selector.ingredients": "Ingredients", + "exception.ingredient.missing": "Not enough ingredients", + "exception.ingredient.space": "Not enough space for", + "exception.permission.edit": "You are not allowed to edit more than %s blocks", + "exception.permission.place.color": "You are not allowed to place something with alpha below %s", + "exception.permission.place": "You are not allowed to place more than %s blocks", + "exception.permission.density": "Only %s tiles are allowed in block", + "exception.permission.grid": "You are not allowed to use grid %s (maximum is %s)", + "exception.door.notloaded": "Cannot interact with door (not all tiles are loaded)", + "exception.door.brokenparent": "Cannot interact with door (broken connection to parent)", + "exception.door.brokenchild": "Cannot interact with door (broken connection to child)", + "exception.door.notenoughspace": "Something is in the way", + "exception.pattern.empty": "empty", + "exception.pattern.circular": "circular reference", + "exception.pattern.novalidchildren": "broken children", + "exception.permission.convert": "Cannot edit more than %s blocks", + "exception.permission.area-protected": "area protected", + "exception.permission.recipe.size": "Recipe area is too large (maximum %s blocks allowed)", + "glove.mode.pixel": "像素模式", + "glove.mode.blueprint": "蓝图模式", + "glove.mode.replace": "替换模式", + "shape.tile": "块", + "shape.type": "Tiles of Type", + "shape.box": "长方体", + "shape.connected": "Connected Tiles", + "shape.slice": "斜面", + "shape.inner_corner": "Inner Slope Corner", + "shape.outer_corner": "Outer Slope Corner", + "shape.polygon": "Pixel Polygon", + "shape.wall": "Wall", + "shape.pillar": "Pillar", + "shape.curve": "Curve", + "shape.curvewall": "Curved Wall", + "shape.cylinder": "Cylinder", + "shape.sphere": "椭球", + "shape.pyramid": "Pyramid", + "placement.mode.normal": "普通模式", + "placement.mode.normal.tooltip": "Can only be placed if there is space for all tiles in the aimed block.", + "placement.mode.placestructure": "Can place structures.", + "placement.mode.fill": "填充模式", + "placement.mode.fill.tooltip": "Will try to fill in the tiles if they don't fit.", + "placement.mode.all": "所有模式", + "placement.mode.all.tooltip": "Can only be placed if there is space for all tiles.", + "placement.mode.overwrite": "覆盖模式", + "placement.mode.overwrite.tooltip": "Will place all tiles and remove the overlapping space.\nCannot remove structure tiles.", + "placement.mode.overwrite_all": "覆盖所有模式", + "placement.mode.overwrite_all.tooltip": "Will place all tiles and remove the entire block.\nCannot remove structure tiles.", + "placement.mode.replace": "替换模式", + "placement.mode.replace.tooltip": "Will only place the tiles at the overlapping space.\nCannot removed structure tiles.", + "placement.mode.stencil": "Stencil Mode", + "placement.mode.stencil.tooltip": "Will remove all tiles at the overlapping space.\nDoes not place anything.", + "placement.mode.colorize": "上色模式", + "placement.mode.colorize.tooltip": "Will color all tiles at the overlapping space.\nDoes not place anything.", + "structure.none": "无", + "structure.simple.fixed": "固定", + "structure.simple.chair": "椅子", + "structure.simple.ladder": "梯子", + "structure.simple.bed": "床", + "structure.simple.storage": "存储", + "structure.simple.noclip": "No-clip", + "structure.door.axis": "转轴门", + "structure.door.sliding": "推拉门", + "structure.door.advanced": "高级门", + "structure.door.activator": "门激活器", + "structure.simple.light": "灯", + "structure.simple.message": "Message", + "structure.fixed": "固定", + "structure.chair": "椅子", + "structure.ladder": "梯子", + "structure.bed": "床", + "structure.storage": "存储", + "structure.noclip": "No-clip", + "structure.axis": "转轴门", + "structure.sliding": "推拉门", + "structure.advanced": "高级门", + "structure.activator": "门激活器", + "structure.light": "灯", + "structure.message": "Message", + "structure.workbench": "Little Workbench", + "structure.importer": "Little Importer", + "structure.exporter": "Little Exporter", + "structure.blankomatic": "Blank-o-matic", + "structure.single_cable1": "Single Cable (1-bit)", + "structure.single_cable4": "Single Cable (4-bit)", + "structure.single_cable16": "Single Cable (16-bit)", + "structure.single_input1": "Single Input (1-bit)", + "structure.single_input4": "Single Input (4-bit)", + "structure.single_input16": "Single Input (16-bit)", + "structure.single_output1": "Single Output (1-bit)", + "structure.single_output4": "Single Output (4-bit)", + "structure.single_output16": "Single Output (16-bit)", + "structure.particle_emitter": "Particle Emitter", + "structure.signal_display_16": "Signal Display (16 bit)", + "structure.item_holder": "Item Holder", + "structure.structure_builder": "Structure Builder", + "structure.daylight_sensor": "Daylight Sensor", + "structure.description.daylight_sensor": "Outputs a signal during daytime.", + "structure.daylight_sensor4": "Daylight Sensor (4 bit)", + "structure.description.daylight_sensor4": "Outputs a signal during daytime.\nHas a 4 bit output.", + "structure.clock_sensor": "Clock Sensor", + "structure.description.clock_sensor": "Outputs the time of the day from 0 to 16.", + "structure.clock_sensor4": "Clock Sensor (4 bit)", + "structure.description.clock_sensor4": "Outputs the time of the day from 0 to 16.\nHas a 4 bit output.", + "structure.clock_sensor16": "Precise Clock Sensor (16 bit)", + "structure.description.clock_sensor16": "Outputs the time of the day from 0 to 24000.\nHas a 16 bit output.", + "gui.signal.components": "组件", + "gui.signal.out": "输出", + "gui.signal.configuration.result": "结果:", + "gui.signal.configuration.addop": "+", + "gui.signal.configuration.add": "+", + "gui.signal.configuration.input.operation.type.none": "无", + "gui.signal.configuration.input.operation.type.operation": "operation", + "gui.signal.configuration.input.operation.type.pattern": "pattern", + "gui.signal.configuration.input.operation.type.equation": "equation", + "signal.mode.equal": "相等", + "signal.mode.toggle": "切换", + "signal.mode.pulse": "脉冲", + "signal.mode.threshold": "THRESHOLD", + "signal.mode.stabilizer": "STABILIZER", + "signal.mode.extender": "EXTENDER", + "gui.filter": "Filter", + "gui.filter.block": "通过方块", + "gui.filter.block_tag": "通过Tag", + "gui.filter.color": "通过颜色", + "gui.filter.group": "Group", + "gui.filter.or": "至少一个", + "gui.filter.and": "全部", + "gui.filter.not_or": "无", + "gui.filter.not_and": "Not all", + "gui.signal.length": "长度" +} diff --git a/src/main/resources/data/littletiles/tags/entity_type/no_collision.json b/src/main/resources/data/littletiles/tags/entity_type/no_collision.json index 1e5a0b140..1d7f71b9b 100644 --- a/src/main/resources/data/littletiles/tags/entity_type/no_collision.json +++ b/src/main/resources/data/littletiles/tags/entity_type/no_collision.json @@ -1,7 +1,13 @@ { "replace": false, "values": [ - "create:carriage_contraption", - "create:stationary_contraption" + { + "id": "create:carriage_contraption", + "required": false + }, + { + "id": "create:stationary_contraption", + "required": false + } ] } \ No newline at end of file