From 8eabd4f303d36ae26f99392db9bb1b45c5dbe7c3 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Fri, 20 Oct 2023 13:32:38 +0100 Subject: [PATCH] Fix signs being empty when placed As of 1.20, sign messages are immutable - we need to do text = text.setMesssage(...) instead. Also do a tiny bit of cleanup to this function while we're here. Probably not the best use of my lunch break :D:. Fixes #1611. --- .../turtle/core/TurtlePlaceCommand.java | 28 ++-- .../computercraft/gametest/Turtle_Test.kt | 21 +++ .../structures/turtle_test.place_sign.snbt | 137 ++++++++++++++++++ 3 files changed, 170 insertions(+), 16 deletions(-) create mode 100644 projects/common/src/testMod/resources/data/cctest/structures/turtle_test.place_sign.snbt diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index 0fa542706..cad9fc63e 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -27,7 +27,6 @@ import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.level.block.entity.SignText; import net.minecraft.world.level.block.state.BlockState; @@ -186,7 +185,7 @@ public class TurtlePlaceCommand implements TurtleCommand { tile = world.getBlockEntity(position.relative(side)); } - if (tile instanceof SignBlockEntity) setSignText(world, tile, message); + if (tile instanceof SignBlockEntity sign) setSignText(world, sign, message); } return placed; @@ -220,23 +219,20 @@ public class TurtlePlaceCommand implements TurtleCommand { return InteractionResult.PASS; } - private static void setSignText(Level world, BlockEntity tile, String message) { - var signTile = (SignBlockEntity) tile; - var split = Splitter.on('\n').splitToList(message); - var firstLine = split.size() <= 2 ? 1 : 0; + private static void setSignText(Level world, SignBlockEntity sign, String message) { + var lines = Splitter.on('\n').splitToList(message); + var firstLine = lines.size() <= 2 ? 1 : 0; var signText = new SignText(); - for (var i = 0; i < 4; i++) { - if (i >= firstLine && i < firstLine + split.size()) { - var line = split.get(i - firstLine); - signText.setMessage(i, line.length() > 15 - ? Component.literal(line.substring(0, 15)) - : Component.literal(line) - ); - } + for (int i = 0, len = Math.min(lines.size(), 4); i < len; i++) { + var line = lines.get(i); + signText = signText.setMessage(i + firstLine, line.length() > 15 + ? Component.literal(line.substring(0, 15)) + : Component.literal(line) + ); } - signTile.setText(signText, true); - world.sendBlockUpdated(tile.getBlockPos(), tile.getBlockState(), tile.getBlockState(), Block.UPDATE_ALL); + sign.setText(signText, true); + world.sendBlockUpdated(sign.getBlockPos(), sign.getBlockState(), sign.getBlockState(), Block.UPDATE_ALL); } private static final class ErrorMessage { diff --git a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt index 15dcd9afa..03f998947 100644 --- a/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt +++ b/projects/common/src/testMod/kotlin/dan200/computercraft/gametest/Turtle_Test.kt @@ -37,6 +37,7 @@ import net.minecraft.world.item.Items import net.minecraft.world.item.enchantment.Enchantments import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.FenceBlock +import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.state.properties.BlockStateProperties import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.array @@ -86,6 +87,26 @@ class Turtle_Test { thenExecute { helper.assertBlockPresent(Blocks.LAVA, BlockPos(2, 2, 2)) } } + /** + * Checks turtles can write to signs. + * + * @see [#1611](https://github.com/cc-tweaked/CC-Tweaked/issues/1611) + */ + @GameTest + fun Place_sign(helper: GameTestHelper) = helper.sequence { + thenOnComputer { + turtle.place(ObjectArguments("Test\nmessage")).await() + .assertArrayEquals(true, message = "Placed sign") + } + thenExecute { + val sign = helper.getBlockEntity(BlockPos(2, 2, 1), BlockEntityType.SIGN) + val lines = listOf("", "Test", "message", "") + for ((i, line) in lines.withIndex()) { + assertEquals(line, sign.frontText.getMessage(i, false).string, "Line $i") + } + } + } + /** * Checks that calling [net.minecraft.world.item.Item.use] will not place blocks too far away. * diff --git a/projects/common/src/testMod/resources/data/cctest/structures/turtle_test.place_sign.snbt b/projects/common/src/testMod/resources/data/cctest/structures/turtle_test.place_sign.snbt new file mode 100644 index 000000000..bca86b1cd --- /dev/null +++ b/projects/common/src/testMod/resources/data/cctest/structures/turtle_test.place_sign.snbt @@ -0,0 +1,137 @@ +{ + DataVersion: 3465, + size: [5, 5, 5], + data: [ + {pos: [0, 0, 0], state: "minecraft:polished_andesite"}, + {pos: [0, 0, 1], state: "minecraft:polished_andesite"}, + {pos: [0, 0, 2], state: "minecraft:polished_andesite"}, + {pos: [0, 0, 3], state: "minecraft:polished_andesite"}, + {pos: [0, 0, 4], state: "minecraft:polished_andesite"}, + {pos: [1, 0, 0], state: "minecraft:polished_andesite"}, + {pos: [1, 0, 1], state: "minecraft:polished_andesite"}, + {pos: [1, 0, 2], state: "minecraft:polished_andesite"}, + {pos: [1, 0, 3], state: "minecraft:polished_andesite"}, + {pos: [1, 0, 4], state: "minecraft:polished_andesite"}, + {pos: [2, 0, 0], state: "minecraft:polished_andesite"}, + {pos: [2, 0, 1], state: "minecraft:polished_andesite"}, + {pos: [2, 0, 2], state: "minecraft:polished_andesite"}, + {pos: [2, 0, 3], state: "minecraft:polished_andesite"}, + {pos: [2, 0, 4], state: "minecraft:polished_andesite"}, + {pos: [3, 0, 0], state: "minecraft:polished_andesite"}, + {pos: [3, 0, 1], state: "minecraft:polished_andesite"}, + {pos: [3, 0, 2], state: "minecraft:polished_andesite"}, + {pos: [3, 0, 3], state: "minecraft:polished_andesite"}, + {pos: [3, 0, 4], state: "minecraft:polished_andesite"}, + {pos: [4, 0, 0], state: "minecraft:polished_andesite"}, + {pos: [4, 0, 1], state: "minecraft:polished_andesite"}, + {pos: [4, 0, 2], state: "minecraft:polished_andesite"}, + {pos: [4, 0, 3], state: "minecraft:polished_andesite"}, + {pos: [4, 0, 4], state: "minecraft:polished_andesite"}, + {pos: [0, 1, 0], state: "minecraft:air"}, + {pos: [0, 1, 1], state: "minecraft:air"}, + {pos: [0, 1, 2], state: "minecraft:air"}, + {pos: [0, 1, 3], state: "minecraft:air"}, + {pos: [0, 1, 4], state: "minecraft:air"}, + {pos: [1, 1, 0], state: "minecraft:air"}, + {pos: [1, 1, 1], state: "minecraft:air"}, + {pos: [1, 1, 2], state: "minecraft:air"}, + {pos: [1, 1, 3], state: "minecraft:air"}, + {pos: [1, 1, 4], state: "minecraft:air"}, + {pos: [2, 1, 0], state: "minecraft:air"}, + {pos: [2, 1, 1], state: "minecraft:air"}, + {pos: [2, 1, 2], state: "computercraft:turtle_normal{facing:north,waterlogged:false}", nbt: {ComputerId: 1, Fuel: 0, Items: [{Count: 1b, Slot: 0b, id: "minecraft:oak_sign"}], Label: "turtle_test.place_sign", On: 1b, Owner: {LowerId: -7553144124013011039L, Name: "Player840", UpperId: 8473952144820417152L}, Slot: 0, id: "computercraft:turtle_normal"}}, + {pos: [2, 1, 3], state: "minecraft:air"}, + {pos: [2, 1, 4], state: "minecraft:air"}, + {pos: [3, 1, 0], state: "minecraft:air"}, + {pos: [3, 1, 1], state: "minecraft:air"}, + {pos: [3, 1, 2], state: "minecraft:air"}, + {pos: [3, 1, 3], state: "minecraft:air"}, + {pos: [3, 1, 4], state: "minecraft:air"}, + {pos: [4, 1, 0], state: "minecraft:air"}, + {pos: [4, 1, 1], state: "minecraft:air"}, + {pos: [4, 1, 2], state: "minecraft:air"}, + {pos: [4, 1, 3], state: "minecraft:air"}, + {pos: [4, 1, 4], state: "minecraft:air"}, + {pos: [0, 2, 0], state: "minecraft:air"}, + {pos: [0, 2, 1], state: "minecraft:air"}, + {pos: [0, 2, 2], state: "minecraft:air"}, + {pos: [0, 2, 3], state: "minecraft:air"}, + {pos: [0, 2, 4], state: "minecraft:air"}, + {pos: [1, 2, 0], state: "minecraft:air"}, + {pos: [1, 2, 1], state: "minecraft:air"}, + {pos: [1, 2, 2], state: "minecraft:air"}, + {pos: [1, 2, 3], state: "minecraft:air"}, + {pos: [1, 2, 4], state: "minecraft:air"}, + {pos: [2, 2, 0], state: "minecraft:air"}, + {pos: [2, 2, 1], state: "minecraft:air"}, + {pos: [2, 2, 2], state: "minecraft:air"}, + {pos: [2, 2, 3], state: "minecraft:air"}, + {pos: [2, 2, 4], state: "minecraft:air"}, + {pos: [3, 2, 0], state: "minecraft:air"}, + {pos: [3, 2, 1], state: "minecraft:air"}, + {pos: [3, 2, 2], state: "minecraft:air"}, + {pos: [3, 2, 3], state: "minecraft:air"}, + {pos: [3, 2, 4], state: "minecraft:air"}, + {pos: [4, 2, 0], state: "minecraft:air"}, + {pos: [4, 2, 1], state: "minecraft:air"}, + {pos: [4, 2, 2], state: "minecraft:air"}, + {pos: [4, 2, 3], state: "minecraft:air"}, + {pos: [4, 2, 4], state: "minecraft:air"}, + {pos: [0, 3, 0], state: "minecraft:air"}, + {pos: [0, 3, 1], state: "minecraft:air"}, + {pos: [0, 3, 2], state: "minecraft:air"}, + {pos: [0, 3, 3], state: "minecraft:air"}, + {pos: [0, 3, 4], state: "minecraft:air"}, + {pos: [1, 3, 0], state: "minecraft:air"}, + {pos: [1, 3, 1], state: "minecraft:air"}, + {pos: [1, 3, 2], state: "minecraft:air"}, + {pos: [1, 3, 3], state: "minecraft:air"}, + {pos: [1, 3, 4], state: "minecraft:air"}, + {pos: [2, 3, 0], state: "minecraft:air"}, + {pos: [2, 3, 1], state: "minecraft:air"}, + {pos: [2, 3, 2], state: "minecraft:air"}, + {pos: [2, 3, 3], state: "minecraft:air"}, + {pos: [2, 3, 4], state: "minecraft:air"}, + {pos: [3, 3, 0], state: "minecraft:air"}, + {pos: [3, 3, 1], state: "minecraft:air"}, + {pos: [3, 3, 2], state: "minecraft:air"}, + {pos: [3, 3, 3], state: "minecraft:air"}, + {pos: [3, 3, 4], state: "minecraft:air"}, + {pos: [4, 3, 0], state: "minecraft:air"}, + {pos: [4, 3, 1], state: "minecraft:air"}, + {pos: [4, 3, 2], state: "minecraft:air"}, + {pos: [4, 3, 3], state: "minecraft:air"}, + {pos: [4, 3, 4], state: "minecraft:air"}, + {pos: [0, 4, 0], state: "minecraft:air"}, + {pos: [0, 4, 1], state: "minecraft:air"}, + {pos: [0, 4, 2], state: "minecraft:air"}, + {pos: [0, 4, 3], state: "minecraft:air"}, + {pos: [0, 4, 4], state: "minecraft:air"}, + {pos: [1, 4, 0], state: "minecraft:air"}, + {pos: [1, 4, 1], state: "minecraft:air"}, + {pos: [1, 4, 2], state: "minecraft:air"}, + {pos: [1, 4, 3], state: "minecraft:air"}, + {pos: [1, 4, 4], state: "minecraft:air"}, + {pos: [2, 4, 0], state: "minecraft:air"}, + {pos: [2, 4, 1], state: "minecraft:air"}, + {pos: [2, 4, 2], state: "minecraft:air"}, + {pos: [2, 4, 3], state: "minecraft:air"}, + {pos: [2, 4, 4], state: "minecraft:air"}, + {pos: [3, 4, 0], state: "minecraft:air"}, + {pos: [3, 4, 1], state: "minecraft:air"}, + {pos: [3, 4, 2], state: "minecraft:air"}, + {pos: [3, 4, 3], state: "minecraft:air"}, + {pos: [3, 4, 4], state: "minecraft:air"}, + {pos: [4, 4, 0], state: "minecraft:air"}, + {pos: [4, 4, 1], state: "minecraft:air"}, + {pos: [4, 4, 2], state: "minecraft:air"}, + {pos: [4, 4, 3], state: "minecraft:air"}, + {pos: [4, 4, 4], state: "minecraft:air"} + ], + entities: [], + palette: [ + "minecraft:polished_andesite", + "minecraft:air", + "computercraft:turtle_normal{facing:north,waterlogged:false}" + ] +}