From 9cbe7e950bf9481bdff2a1cc238db376d37b3cd1 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 10:45:10 +0200 Subject: [PATCH 1/7] docs: list the void well and dragon, and replay gallery scenes from their signs Co-Authored-By: Claude Opus 5.5 --- GLOSSARY.md | 2 +- README.md | 5 +++-- ...works-ships-an-optional-gallery-pack-ahead-of-libworks.md | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/GLOSSARY.md b/GLOSSARY.md index 70ca5cd..1d4ee7b 100644 --- a/GLOSSARY.md +++ b/GLOSSARY.md @@ -26,7 +26,7 @@ The creative tab the suite's Modules share, registered by the libworks-runtime n _Avoid_: Voidworks tab, creative tab (alone) **Gallery pack**: -The optional datapack in the jar, "Voidworks Gallery", offered and off by default, whose functions lay the Module's features out as working scenes, one plot per scene with a sign naming it, for an operator player to see them at work (ADR 0008). Unlike `dev_pack/` and `gametest_pack/`, the datapacks only the Module's own runs load, it ships. It holds functions only, so turning it on changes nothing about how Voidworks plays. +The optional datapack in the jar, "Voidworks Gallery", offered and off by default, whose functions lay the Module's features out as working scenes, one plot per scene with a sign naming it, which replays the scene when clicked, for an operator player to see them at work (ADR 0008). Unlike `dev_pack/` and `gametest_pack/`, the datapacks only the Module's own runs load, it ships. It holds functions only, so turning it on changes nothing about how Voidworks plays. _Avoid_: showcase (the `/voidworks showcase` command), demo world ### Void diff --git a/README.md b/README.md index dc19b53..c31b184 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ To play Voidworks beside every other FactoryWorks mod, install the [FactoryWorks ## Features +- **The Void Well.** A large store of motes on a Voidstone network, built as a 5×5×5 well, and the stop where a Void Dragon loads, unloads and heals. +- **The Void Dragon.** Raised on void from a Dragonling, it carries motes or matter between Void Wells, diving through the void between them, across dimensions. - **Three Void Displacers, one per dimension.** The Overworld Displacer swaps fed blocks into the terrain around it and gives you that terrain back. The End Displacer grows its body out into the air, and harvests higher over the open void. The Nether Displacer drinks lava lakes and fills its tank, which any pipe can drain. Each harvests a fixed number of times, then turns to Voidstone. - **Density.** What you feed sets how many motes a harvest yields: copper and coal blocks are the lightest, diamond and netherite blocks the densest. - **Voidstone networks.** Touching Voidstone is one network holding one pool of motes, and every Voidstone adds room. @@ -26,12 +28,11 @@ To play Voidworks beside every other FactoryWorks mod, install the [FactoryWorks - **The Mutation Chamber.** Upgrades items up their Family for motes, with a chance per upgrade. It has no screen: hoppers and belts feed and empty it. - **The Unmaking Chamber.** Breaks an item down into its crafting recipe's ingredients for motes, each coming back by chance at a yield that rises as it works. - **The Void Crucible.** Upgrades for free, slowly. It is fastest in the End and slowest in the Nether, and Crucibles working near each other share one rate. -- **The Unmaking Chamber.** Breaks an item down into the ingredients of its crafting recipe for motes. Each ingredient comes back by chance, from 25% at first rising toward 75% the more the Chamber has spent. - **Jade support.** Jade shows a network's motes and what they are worth where you stand, a machine's upgrade, progress and what stalls it, and how much of a Dormant machine's cost is paid. Voidworks runs without Jade. ## Gallery -Voidworks carries an optional datapack, **Voidworks Gallery**, that builds its features as working scenes beside you. It is off in every world until you turn it on, in the world's Data Packs screen or with `/datapack enable "mod/voidworks:gallery_pack"`, then run `/function voidworks:gallery/build`, or `/function voidworks:gallery/` for one scene. It needs cheats in single player (on at creation, or Open to LAN with cheats) and operator permission on a server, and it builds only blocks and what its scenes need an owner for: run it as a player, who owns them. Its first scene is a Void Dragon carrying between two Void Wells. +Voidworks carries an optional datapack, **Voidworks Gallery**, that builds its features as working scenes beside you. It is off in every world until you turn it on, in the world's Data Packs screen or with `/datapack enable "mod/voidworks:gallery_pack"`, then run `/function voidworks:gallery/build`, or `/function voidworks:gallery/` for one scene. It needs cheats in single player (on at creation, or Open to LAN with cheats) and operator permission on a server, and it builds only blocks and what its scenes need an owner for: run it as a player, who owns them. Clicking a scene's sign builds it again from the start, to watch it play out. ## For pack authors diff --git a/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md b/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md index 3760cb1..61f2823 100644 --- a/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md +++ b/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md @@ -44,5 +44,9 @@ dragon kill bringing back the founder egg. - Building the dragon scene changes server-wide records as well as blocks, unlike #691's other galleries, which change blocks alone. Its own Wells' records go with their cores, and its dragons with its `dragon remove`, so building it again leaves one dragon. +- A scene is replayed from its own sign: a click event runs its function again, rebuilding it from + the start, so a scene that runs out (a Displacer's harvests, a Dormant machine waking) can be + watched after `build` has laid out the whole row. A sign needs no setting, where a command block + is off on a server until `enable-command-block` is set, and the Gallery already needs an operator. - A function run from the server console has no player to own the scene's Wells and dragon, so the dragon scene fails there; it is for an operator player. From 241f238af8276ef3a3354b613e485b57cf113714 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 10:56:16 +0200 Subject: [PATCH 2/7] feat: build a gallery scene for each feature, replayed from its sign Closes #77 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + README.md | 2 +- .../voidworks/gametest/GalleryTests.java | 130 +++++++++++++++++- .../assets/voidworks/lang/en_us.json | 40 ++++++ .../function/gallery/build.mcfunction | 17 ++- .../function/gallery/chamber.mcfunction | 8 ++ .../function/gallery/clear.mcfunction | 7 + .../function/gallery/density.mcfunction | 10 ++ .../function/gallery/density/one.mcfunction | 9 ++ .../gallery/dormant_machines.mcfunction | 8 ++ .../function/gallery/elsewhere.mcfunction | 5 + .../function/gallery/end_displacer.mcfunction | 6 + .../gallery/end_displacer/working.mcfunction | 3 + .../gallery/mutation_chamber.mcfunction | 4 + .../gallery/nether_displacer.mcfunction | 7 + .../nether_displacer/working.mcfunction | 5 + .../gallery/overworld_displacer.mcfunction | 7 + .../overworld_displacer/working.mcfunction | 7 + .../function/gallery/sign.mcfunction | 3 + .../gallery/unmaking_chamber.mcfunction | 4 + .../function/gallery/void_crucible.mcfunction | 8 ++ .../function/gallery/void_dragon.mcfunction | 2 +- .../function/gallery/void_siphon.mcfunction | 8 ++ .../gallery/voidstone_networks.mcfunction | 8 ++ 24 files changed, 298 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/dormant_machines.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/elsewhere.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer/working.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/mutation_chamber.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer/working.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/sign.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/unmaking_chamber.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/voidstone_networks.mcfunction diff --git a/CHANGELOG.md b/CHANGELOG.md index ca50c91..5311420 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Written for Consumers: what a mod building against Voidworks can use, or will se - With Groundworks present, a Void Well is placed in one step from its core: holding a core shows the whole Well in Groundworks' preview, and a click places the core, its 56 casing and 16 rim around an open shaft, paid from the inventory, all or nothing, the core facing out of its wall toward the player, so the Well is whole at once. Once placed it is an ordinary Well, and breaking a casing stops it as before. Without Groundworks nothing changes: it is built by hand. The Assembly is data alone, `data/voidworks/groundworks/assembly/void_well.json`, its core made a Key by the `groundworks:assembly_keys` block tag. Voidworks still requires nothing but Minecraft and NeoForge. (#65) - **Breaking:** a grown Void Dragon ages through four life stages, young, adult, senior and old, by the motes it unloads over its life, each stage `lifeStageMotes` (524,288) long, changing only at a stop (ADR 0010). Each stage multiplies its load and speed (`lifeStageLoads` 1/2/3.5/6, `lifeStageSpeeds` 1/0.6/0.35/0.2 in `voidworks-server.toml`), its speed stacking on its health's share, floored at a quarter; a new load applies from its next load and a new speed from its next dive. Only an adult lays Drained Dragon Eggs: eggs it still owes on turning senior are laid at its next loaded stop, then no more. An old dragon whose stage runs out dies at the end of a stop at a loaded Well, carrying nothing, living on past an unloaded one: it sets any rider down on the Well's rim, lays the eggs it owes, and its presence rises over the Well in a short Ender Dragon death, beams and sound, leaving nothing; nothing else tells its owner. An egg's price now counts its owner's living dragons and eggs soaking, not every dragon they ever hatched, so a death, or `/voidworks dragon remove`, lowers it (`Hatchery.lose`). `/voidworks dragon age ` sets the grown dragon an operator looks at to the start of that stage, owing no egg. Jade shows a dragon's stage, and its presence is sized ×0.8, ×1, ×1.1 or ×1.2 by it. Dragons saved before this start young, their count toward an egg dropped. `Routing` takes a `LifeStages` and `step` returns the dragons that died; `VoidDragonRecord` gains `cargo` and loses `speed()`, now `LifeStages.speed(dragon)`; `DragonReport` gains `stage`. (#54) +- The Gallery pack builds a scene for each feature, in rows of three beside the Void Dragon's: the Overworld, End and Nether Displacers, Density, Voidstone networks, the Void Siphon, Dormant machines, the Mutation and Unmaking Chambers and the Void Crucible, each `voidworks:gallery/`. Clicking a scene's sign builds it again from the start. The End and Nether Displacers work only in their own dimension, so built anywhere else, as the Overworld's and Density's are outside the Overworld, their scene shows the Displacer as an item over a pedestal. (#77) - **Breaking:** a dragon egg's price is datapack data, no longer server config (ADR 0009). The `voidworks:egg_price` block data map, on `voidworks:soaking_dragon_egg`, names an owner's `first_price` (25600 void energy) and its `growth` (2), the multiple each dragon they have hatched or are soaking puts on their next egg; a growth of 1 keeps every egg at the first price, and an egg with no entry is free. `firstEggPrice` is gone from `voidworks-server.toml` and `VoidworksConfig`. `EggPrice.of(dragons)` gives a price, `EggPrice.of(state)` an egg block's entry, and `Hatchery.startSoaking` takes the `EggPrice`; `Hatchery.price` and `Hatchery.codec` give way to `EggPrice.of` and `Hatchery.CODEC`. (#25) - A Void Dragon resting at a Well lands and sits astride its rim, over the shaft, lengthwise along the wall its core is set in so neither head nor tail covers the core, in the Ender Dragon's sitting pose, its wings held still and down, turning its head toward a nearby player. Where blocks fill the room its body takes there, it flies about over the shaft instead and lands once there is room. As it sets off it takes off, then dives into the shaft; mounted by its owner, it takes off to hover, and lands again once they get off. One at work at a Well, loading, unloading, waiting for its owner or setting a rider down, stays in the air, and one back after its chunk unloaded is sitting already. `VoidDragon.perch()` says whether a presence flies, lands, sits or takes off (`VoidDragon.Perch`), `perchYaw()` the heading it keeps meanwhile and `seatPos()` where it sits. A ridden dragon now hovers in place: before, its wandering pulled it slowly about under its rider. (#81) - A Void Dragon resting at a Well whose chunk is not loaded no longer loads that chunk each second to see whether to show it (ADR 0005). diff --git a/README.md b/README.md index c31b184..c33312e 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ To play Voidworks beside every other FactoryWorks mod, install the [FactoryWorks ## Gallery -Voidworks carries an optional datapack, **Voidworks Gallery**, that builds its features as working scenes beside you. It is off in every world until you turn it on, in the world's Data Packs screen or with `/datapack enable "mod/voidworks:gallery_pack"`, then run `/function voidworks:gallery/build`, or `/function voidworks:gallery/` for one scene. It needs cheats in single player (on at creation, or Open to LAN with cheats) and operator permission on a server, and it builds only blocks and what its scenes need an owner for: run it as a player, who owns them. Clicking a scene's sign builds it again from the start, to watch it play out. +Voidworks carries an optional datapack, **Voidworks Gallery**, that builds its features as working scenes beside you. It is off in every world until you turn it on, in the world's Data Packs screen or with `/datapack enable "mod/voidworks:gallery_pack"`, then run `/function voidworks:gallery/build`, or `/function voidworks:gallery/` for one scene. It needs cheats in single player (on at creation, or Open to LAN with cheats) and operator permission on a server, and it builds only blocks and what its scenes need an owner for: run it as a player, who owns them. It lays out a scene for each feature above, in rows of three, and clicking a scene's sign builds it again from the start, to watch it play out. The End and Nether Displacers work only in their own dimension, so run it there to see them at work. ## For pack authors diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java index b2861c4..286a10c 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java @@ -12,6 +12,9 @@ import com.mojang.authlib.GameProfile; import io.github._5thlayer.voidworks.Voidworks; import io.github._5thlayer.voidworks.VoidworksBlocks; +import io.github._5thlayer.voidworks.VoidworksConfig; +import io.github._5thlayer.voidworks.network.MoteNetwork; +import io.github._5thlayer.voidworks.network.VoidstoneNetworks; import io.github._5thlayer.voidworks.dragon.Place; import io.github._5thlayer.voidworks.dragon.SavedVoidDragons; import io.github._5thlayer.voidworks.dragon.Trip; @@ -26,6 +29,9 @@ import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.permissions.PermissionSet; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.util.FakePlayer; @@ -41,13 +47,27 @@ final class GalleryTests { private static final Identifier BUILD = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/build"); private static final Identifier VOID_DRAGON = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/void_dragon"); + private static final Identifier DENSITY = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/density"); + private static final Identifier VOID_CRUCIBLE = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/void_crucible"); + + /** How far east each scene's plot is of the one before it in its row, and how far north each row is of the last. */ + private static final int PLOT_WIDTH = 24; + private static final int ROW_DEPTH = 16; + /** How many scenes a row holds. */ + private static final int ROW = 3; + /** How many scenes {@code build} lays, the Void Dragon's first. */ + private static final int SCENES = 11; /** Where the gallery is run from: the platform's south-west corner, its plots spilling north and east of the platform. */ private static final BlockPos ORIGIN = new BlockPos(0, 1, 8); /** The Void Dragon scene's two Well cores, from where it is run: the reservoir and the Well short of its target. */ private static final BlockPos RESERVOIR = new BlockPos(8, 2, -4); private static final BlockPos SHORT = new BlockPos(20, 2, -4); - /** The Void Dragon scene's plot, from where it is run, its floor included. */ + /** Where a scene's sign stands, from where the scene is run. */ + private static final BlockPos SIGN = new BlockPos(14, 0, 0); + /** The Density scene's four Displacers, from where it is run, coal's to diamond's, each over its one stone. */ + private static final int[] DENSITY_XS = {5, 10, 15, 20}; + /** A scene's plot, from where it is run, its floor included. */ private static final BlockPos PLOT_FROM = new BlockPos(2, -1, -12); private static final BlockPos PLOT_TO = new BlockPos(25, 15, 0); @@ -62,12 +82,17 @@ static void register(VoidworksGameTests.Registrar tests) { GalleryTests::builds); tests.testOnItsOwn("the_void_dragon_scenes_dragon_sets_off_from_its_reservoir_for_the_other_well_and_building_it_again_leaves_one", TICKS, GalleryTests::dragonCarries); + tests.testOnItsOwn("the_gallery_density_scenes_displacers_each_yield_their_densitys_motes", TICKS, + GalleryTests::densityYields); + tests.testOnItsOwn("the_gallery_scenes_sign_clicked_builds_the_scene_again", TICKS, + GalleryTests::signReplays); } private static void builds(GameTestHelper helper) { var server = helper.getLevel().getServer(); var source = operator(helper); GalleryCheck.assertOfferedAndOff(helper, GalleryPack.ID); + forceLoad(helper, true); clearAwayIfItFails(helper, source); var on = GalleryCheck.select(server, GalleryPack.ID, true); var off = new AtomicReference>(); @@ -75,8 +100,21 @@ private static void builds(GameTestHelper helper) { .thenWaitUntil(() -> helper.assertTrue(on.isDone(), "the Gallery pack is not on yet")) .thenExecute(() -> { GalleryCheck.assertRuns(helper, source, BUILD); - GalleryCheck.assertKeyBlocks(helper, helper.absolutePos(ORIGIN), - Map.of(RESERVOIR, VoidworksBlocks.VOID_WELL.get(), SHORT, VoidworksBlocks.VOID_WELL.get())); + GalleryCheck.assertKeyBlocks(helper, helper.absolutePos(ORIGIN), Map.ofEntries( + Map.entry(RESERVOIR, VoidworksBlocks.VOID_WELL.get()), + Map.entry(SHORT, VoidworksBlocks.VOID_WELL.get()), + Map.entry(scene(1, 14, 2, -6), VoidworksBlocks.OVERWORLD_DISPLACER.get()), + // The game tests run in the Overworld, so the End and Nether scenes show + // their Displacers in a frame, behind their signs. + Map.entry(scene(2, SIGN), Blocks.OAK_SIGN), + Map.entry(scene(3, SIGN), Blocks.OAK_SIGN), + Map.entry(scene(4, 20, 1, -6), VoidworksBlocks.OVERWORLD_DISPLACER.get()), + Map.entry(scene(5, 5, 0, -6), VoidworksBlocks.VOIDSTONE.get()), + Map.entry(scene(6, 14, 0, -3), Blocks.CHEST), + Map.entry(scene(7, 14, 0, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), + Map.entry(scene(8, 14, 1, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), + Map.entry(scene(9, 14, 1, -6), VoidworksBlocks.UNMAKING_CHAMBER.get()), + Map.entry(scene(10, 14, 1, -6), VoidworksBlocks.VOID_CRUCIBLE.get()))); off.set(clearAway(helper, source)); }) .thenWaitUntil(() -> assertOff(helper, off)) @@ -111,6 +149,80 @@ private static void dragonCarries(GameTestHelper helper) { .thenSucceed(); } + /** + * The Density scene: each Displacer, fed one block, harvests the stone under it, so its network + * holds the motes one harvest of that Density yields. + */ + private static void densityYields(GameTestHelper helper) { + var server = helper.getLevel().getServer(); + var source = operator(helper); + clearAwayIfItFails(helper, source); + var on = GalleryCheck.select(server, GalleryPack.ID, true); + var off = new AtomicReference>(); + helper.startSequence() + .thenWaitUntil(() -> helper.assertTrue(on.isDone(), "the Gallery pack is not on yet")) + .thenExecute(() -> GalleryCheck.assertRuns(helper, source, DENSITY)) + .thenWaitUntil(() -> { + for (int density = 1; density <= DENSITY_XS.length; density++) { + var stone = helper.absolutePos(ORIGIN).offset(DENSITY_XS[density - 1], 0, -6); + long motes = VoidstoneNetworks.of(helper.getLevel()).at(stone).map(MoteNetwork::total).orElse(0L); + long yield = VoidworksConfig.motes(density); + helper.assertTrue(motes == yield, "Density " + density + "'s network holds " + motes + " motes, not " + yield); + } + }) + .thenExecute(() -> off.set(clearAway(helper, source))) + .thenWaitUntil(() -> assertOff(helper, off)) + .thenSucceed(); + } + + /** A scene's sign, clicked, builds the scene again where it stands: here the Crucible, taken away. */ + private static void signReplays(GameTestHelper helper) { + var server = helper.getLevel().getServer(); + var source = operator(helper); + var crucible = helper.absolutePos(ORIGIN).offset(14, 1, -6); + var sign = helper.absolutePos(ORIGIN).offset(SIGN); + clearAwayIfItFails(helper, source); + var on = GalleryCheck.select(server, GalleryPack.ID, true); + var off = new AtomicReference>(); + helper.startSequence() + .thenWaitUntil(() -> helper.assertTrue(on.isDone(), "the Gallery pack is not on yet")) + .thenExecute(() -> { + GalleryCheck.assertRuns(helper, source, VOID_CRUCIBLE); + helper.getLevel().removeBlock(crucible, false); + helper.assertTrue(helper.getLevel().getBlockEntity(sign) instanceof SignBlockEntity entity + && entity.executeClickCommandsIfPresent(helper.getLevel(), source.getPlayer(), sign, true), + "the scene's sign runs no command when clicked"); + helper.assertTrue(helper.getLevel().getBlockState(crucible).is(VoidworksBlocks.VOID_CRUCIBLE.get()), + "clicking the sign did not build the Crucible again where it stood"); + off.set(clearAway(helper, source)); + }) + .thenWaitUntil(() -> assertOff(helper, off)) + .thenSucceed(); + } + + /** @return the position, from where the gallery is run, of {@code pos} in scene {@code index}, the Void Dragon's 0 */ + private static BlockPos scene(int index, BlockPos pos) { + return pos.east(PLOT_WIDTH * (index % ROW)).north(ROW_DEPTH * (index / ROW)); + } + + /** + * Keeps the chunks the whole gallery stands in loaded, or not, as a player standing where it is + * run would: the game test server loads only those near the test. + */ + private static void forceLoad(GameTestHelper helper, boolean load) { + var from = ChunkPos.containing(helper.absolutePos(ORIGIN.offset(PLOT_FROM).north(ROW_DEPTH * ((SCENES - 1) / ROW)))); + var to = ChunkPos.containing(helper.absolutePos(ORIGIN.offset(scene(ROW - 1, PLOT_TO)))); + for (int x = Math.min(from.x(), to.x()); x <= Math.max(from.x(), to.x()); x++) { + for (int z = Math.min(from.z(), to.z()); z <= Math.max(from.z(), to.z()); z++) { + helper.getLevel().setChunkForced(x, z, load); + } + } + } + + private static BlockPos scene(int index, int x, int y, int z) { + return scene(index, new BlockPos(x, y, z)); + } + /** Waits for the reload that turns the pack off, which a step failing before it never starts. */ private static void assertOff(GameTestHelper helper, AtomicReference> off) { helper.assertTrue(off.get() != null && off.get().isDone(), "the Gallery pack is not off yet"); @@ -130,10 +242,16 @@ private static VoidDragonRecord only(GameTestHelper helper, UUID owner) { * @return the reload, done once the pack is off */ private static CompletableFuture clearAway(GameTestHelper helper, CommandSourceStack source) { - var box = CommandTests.coordinates(helper, ORIGIN.offset(PLOT_FROM)) + " " + CommandTests.coordinates(helper, ORIGIN.offset(PLOT_TO)); var commands = helper.getLevel().getServer().getCommands(); - commands.performPrefixedCommand(source, "voidworks dragon remove " + box); - commands.performPrefixedCommand(source, "fill " + box + " minecraft:air"); + for (int index = 0; index < SCENES; index++) { + // One fill a plot, each within the fill limit. + var box = CommandTests.coordinates(helper, ORIGIN.offset(scene(index, PLOT_FROM))) + + " " + CommandTests.coordinates(helper, ORIGIN.offset(scene(index, PLOT_TO))); + commands.performPrefixedCommand(source, "voidworks dragon remove " + box); + commands.performPrefixedCommand(source, "fill " + box + " minecraft:air"); + } + commands.performPrefixedCommand(source, "kill @e[type=minecraft:item_display,distance=..200]"); + forceLoad(helper, false); return GalleryCheck.select(helper.getLevel().getServer(), GalleryPack.ID, false); } diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index dedecbd..744cb5d 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -31,6 +31,46 @@ "voidworks.gallery.void_dragon.1": "carries motes", "voidworks.gallery.void_dragon.2": "from a reservoir", "voidworks.gallery.void_dragon.3": "to a Well short", + "voidworks.gallery.overworld_displacer": "Overworld Displacer", + "voidworks.gallery.overworld_displacer.1": "swaps coal", + "voidworks.gallery.overworld_displacer.2": "into stone and", + "voidworks.gallery.overworld_displacer.3": "gives stone back", + "voidworks.gallery.end_displacer": "End Displacer", + "voidworks.gallery.end_displacer.1": "grows up", + "voidworks.gallery.end_displacer.2": "into the air", + "voidworks.gallery.end_displacer.3": "in the End only", + "voidworks.gallery.nether_displacer": "Nether Displacer", + "voidworks.gallery.nether_displacer.1": "drinks lava", + "voidworks.gallery.nether_displacer.2": "into its tank", + "voidworks.gallery.nether_displacer.3": "in the Nether only", + "voidworks.gallery.density": "Density", + "voidworks.gallery.density.1": "coal to diamond:", + "voidworks.gallery.density.2": "1, 4, 16 and 64", + "voidworks.gallery.density.3": "motes a harvest", + "voidworks.gallery.voidstone_networks": "Voidstone Networks", + "voidworks.gallery.voidstone_networks.1": "touching Voidstone", + "voidworks.gallery.voidstone_networks.2": "is one network:", + "voidworks.gallery.voidstone_networks.3": "motes crawl", + "voidworks.gallery.void_siphon": "Void Siphon", + "voidworks.gallery.void_siphon.1": "take it, then", + "voidworks.gallery.void_siphon.2": "charge on the full", + "voidworks.gallery.void_siphon.3": "empty on the bare", + "voidworks.gallery.dormant_machines": "Dormant Machines", + "voidworks.gallery.dormant_machines.1": "a Dormant Chamber", + "voidworks.gallery.dormant_machines.2": "soaks its cost", + "voidworks.gallery.dormant_machines.3": "and wakes", + "voidworks.gallery.mutation_chamber": "Mutation Chamber", + "voidworks.gallery.mutation_chamber.1": "upgrades copper", + "voidworks.gallery.mutation_chamber.2": "to iron,", + "voidworks.gallery.mutation_chamber.3": "for motes", + "voidworks.gallery.unmaking_chamber": "Unmaking Chamber", + "voidworks.gallery.unmaking_chamber.1": "breaks buckets", + "voidworks.gallery.unmaking_chamber.2": "into iron,", + "voidworks.gallery.unmaking_chamber.3": "for motes", + "voidworks.gallery.void_crucible": "Void Crucible", + "voidworks.gallery.void_crucible.1": "upgrades copper", + "voidworks.gallery.void_crucible.2": "to iron for free,", + "voidworks.gallery.void_crucible.3": "slowly", "config.jade.plugin_voidworks.chamber": "Mutation Chamber state", "config.jade.plugin_voidworks.crucible": "Void Crucible state", "config.jade.plugin_voidworks.displacer": "Void Displacer state", diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction index 7ed6532..47d9d38 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction @@ -1,5 +1,16 @@ # The Voidworks Gallery: every scene of the Module's features, each building and clearing a plot of -# its own, 24 blocks wide, the first 2 blocks east of where it is run and each further one east of -# the last. Run by an operator player, who owns what the scenes need an owner for (ADR 0008). A -# further scene runs 24 blocks east of the last: execute positioned ~24 ~ ~ run function ... +# its own, 24 blocks wide and 13 deep. The scenes stand in rows of three, read west to east and then +# north, each row 16 blocks north of the one before, so the whole gallery stays near enough to where +# it is run for its machines to keep working. Run by an operator player, who owns what the scenes +# need an owner for (ADR 0008). function voidworks:gallery/void_dragon +execute positioned ~24 ~ ~ run function voidworks:gallery/overworld_displacer +execute positioned ~48 ~ ~ run function voidworks:gallery/end_displacer +execute positioned ~ ~ ~-16 run function voidworks:gallery/nether_displacer +execute positioned ~24 ~ ~-16 run function voidworks:gallery/density +execute positioned ~48 ~ ~-16 run function voidworks:gallery/voidstone_networks +execute positioned ~ ~ ~-32 run function voidworks:gallery/void_siphon +execute positioned ~24 ~ ~-32 run function voidworks:gallery/dormant_machines +execute positioned ~48 ~ ~-32 run function voidworks:gallery/mutation_chamber +execute positioned ~ ~ ~-48 run function voidworks:gallery/unmaking_chamber +execute positioned ~24 ~ ~-48 run function voidworks:gallery/void_crucible diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction new file mode 100644 index 0000000..95ca57d --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction @@ -0,0 +1,8 @@ +# A Chamber's scene: the Chamber built awake, fed from a hopper above and emptied by a hopper below +# into a chest, with 18 Voidstone beside it full of motes to pay for its work. +$setblock ~14 ~1 ~-6 voidworks:$(chamber)[dormant=false]{dormancy:{awake:1b}} +$setblock ~14 ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"$(item)",count:$(count)}]} +setblock ~14 ~ ~-6 minecraft:hopper[facing=south] +setblock ~14 ~ ~-5 minecraft:chest +fill ~12 ~ ~-7 ~13 ~2 ~-5 voidworks:voidstone +voidworks mote ~13 ~1 ~-6 5 diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction new file mode 100644 index 0000000..4dcb13f --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction @@ -0,0 +1,7 @@ +# Clears a scene's plot, from ~2 to ~25 east and from ~-12 to ~0 south, 16 high, onto a smooth stone +# floor, which no Displacer harvests: the item displays and dropped items in it, then its blocks. +execute positioned ~2 ~-1 ~-12 as @e[type=minecraft:item_display,dx=23,dy=16,dz=12] run kill @s +execute positioned ~2 ~-1 ~-12 as @e[type=minecraft:item,dx=23,dy=16,dz=12] run kill @s +fill ~2 ~-1 ~-12 ~25 ~15 ~ minecraft:structure_void +fill ~2 ~-1 ~-12 ~25 ~-1 ~ minecraft:smooth_stone +fill ~2 ~ ~-12 ~25 ~15 ~ minecraft:air diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction new file mode 100644 index 0000000..fba0b2e --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction @@ -0,0 +1,10 @@ +# Density: four Overworld Displacers, each fed one block of a Density from coal to diamond, each +# harvesting the one stone under it into a network of four Voidstone around that stone, then turning +# to Voidstone itself. Jade on each network shows the motes its one harvest yielded: 1, 4, 16, 64. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"density"} +execute if dimension minecraft:overworld run function voidworks:gallery/density/one {x:5,block:"minecraft:coal_block"} +execute if dimension minecraft:overworld run function voidworks:gallery/density/one {x:10,block:"minecraft:iron_block"} +execute if dimension minecraft:overworld run function voidworks:gallery/density/one {x:15,block:"minecraft:gold_block"} +execute if dimension minecraft:overworld run function voidworks:gallery/density/one {x:20,block:"minecraft:diamond_block"} +execute unless dimension minecraft:overworld run function voidworks:gallery/elsewhere {item:"voidworks:overworld_void_displacer"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction new file mode 100644 index 0000000..fe2fef4 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction @@ -0,0 +1,9 @@ +# One Density's Displacer at ~x, the one stone under it ringed by four Voidstone: room for 80 motes, +# more than a diamond block's 64. +$setblock ~$(x) ~ ~-6 minecraft:stone +$setblock ~$(x) ~ ~-7 voidworks:voidstone +$setblock ~$(x) ~ ~-5 voidworks:voidstone +$execute positioned ~$(x) ~ ~-6 run setblock ~-1 ~ ~ voidworks:voidstone +$execute positioned ~$(x) ~ ~-6 run setblock ~1 ~ ~ voidworks:voidstone +$setblock ~$(x) ~1 ~-6 voidworks:overworld_void_displacer +$setblock ~$(x) ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"$(block)",count:1}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/dormant_machines.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/dormant_machines.mcfunction new file mode 100644 index 0000000..8488d5a --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/dormant_machines.mcfunction @@ -0,0 +1,8 @@ +# Dormant machines: a Dormant Mutation Chamber at the end of a line of eight Voidstone, motes put in +# at the line's far end. They crawl to it, it soaks its cost from them, and wakes. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"dormant_machines"} +fill ~6 ~ ~-6 ~13 ~ ~-6 voidworks:voidstone +setblock ~14 ~ ~-6 voidworks:mutation_chamber +# One grade above the End's Void Pressure over the open void: 16 pay its shipped cost anywhere. +voidworks mote ~6 ~ ~-6 5 16 diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/elsewhere.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/elsewhere.mcfunction new file mode 100644 index 0000000..dc88155 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/elsewhere.mcfunction @@ -0,0 +1,5 @@ +# A Displacer built outside its own dimension drops as its item on its first tick, so a scene built +# elsewhere shows it as an item display over a pedestal behind the sign, which names its dimension. +# A display, not an item frame: a frame's NBT names its block absolutely, which a function cannot. +setblock ~14 ~ ~-2 minecraft:smooth_stone +$execute align xyz run summon minecraft:item_display ~14.5 ~1.5 ~-1.5 {item:{id:"$(item)",count:1},billboard:"vertical"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction new file mode 100644 index 0000000..bfec006 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction @@ -0,0 +1,6 @@ +# The End Displacer: one awake, facing up, fed coal blocks from a hopper beside it. It grows its body +# of Voidstone up into the air until its harvests are spent. Outside the End it is shown as an item. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"end_displacer"} +execute if dimension minecraft:the_end run function voidworks:gallery/end_displacer/working +execute unless dimension minecraft:the_end run function voidworks:gallery/elsewhere {item:"voidworks:end_void_displacer"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer/working.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer/working.mcfunction new file mode 100644 index 0000000..abf0604 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer/working.mcfunction @@ -0,0 +1,3 @@ +# Built awake, its Dormant cost already paid, so it starts at once. +setblock ~14 ~ ~-6 voidworks:end_void_displacer[dormant=false,facing=up]{dormancy:{awake:1b}} +setblock ~13 ~ ~-6 minecraft:hopper[facing=east]{Items:[{Slot:0b,id:"minecraft:coal_block",count:64}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/mutation_chamber.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/mutation_chamber.mcfunction new file mode 100644 index 0000000..f7f4943 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/mutation_chamber.mcfunction @@ -0,0 +1,4 @@ +# The Mutation Chamber: copper ingots upgraded to iron, each by chance, for motes. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"mutation_chamber"} +function voidworks:gallery/chamber {chamber:"mutation_chamber",item:"minecraft:copper_ingot",count:16} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer.mcfunction new file mode 100644 index 0000000..9976d0f --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer.mcfunction @@ -0,0 +1,7 @@ +# The Nether Displacer: one awake beside a walled pool of nine lava sources, fed coal blocks from a +# hopper above. It drinks the pool into its tank, a bucket a source, leaving Voidstone. Outside the +# Nether it is shown as an item. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"nether_displacer"} +execute if dimension minecraft:the_nether run function voidworks:gallery/nether_displacer/working +execute unless dimension minecraft:the_nether run function voidworks:gallery/elsewhere {item:"voidworks:nether_void_displacer"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction new file mode 100644 index 0000000..1042f41 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction @@ -0,0 +1,5 @@ +# The pool's wall holds the lava on the floor; the Displacer, built awake, takes the wall's east side. +fill ~10 ~ ~-8 ~14 ~ ~-4 minecraft:smooth_stone +fill ~11 ~ ~-7 ~13 ~ ~-5 minecraft:lava +setblock ~14 ~ ~-6 voidworks:nether_void_displacer[dormant=false]{dormancy:{awake:1b}} +setblock ~14 ~1 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"minecraft:coal_block",count:16}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer.mcfunction new file mode 100644 index 0000000..236d2d6 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer.mcfunction @@ -0,0 +1,7 @@ +# The Overworld Displacer: one in the top of a mound of stone, fed coal blocks from a hopper above +# and emptied into a chest below. It swaps the mound's stone for its coal, giving the stone back, +# until its 64 harvests are spent and it turns to Voidstone. Elsewhere it is shown as an item. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"overworld_displacer"} +execute if dimension minecraft:overworld run function voidworks:gallery/overworld_displacer/working +execute unless dimension minecraft:overworld run function voidworks:gallery/elsewhere {item:"voidworks:overworld_void_displacer"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer/working.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer/working.mcfunction new file mode 100644 index 0000000..09f4858 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/overworld_displacer/working.mcfunction @@ -0,0 +1,7 @@ +# 5×5×3 of stone, 72 once the Displacer, its output hopper and chest are set in it: more than it +# harvests, on a floor it never harvests. +fill ~12 ~ ~-8 ~16 ~2 ~-4 minecraft:stone +setblock ~14 ~ ~-6 minecraft:chest +setblock ~14 ~1 ~-6 minecraft:hopper[facing=down] +setblock ~14 ~2 ~-6 voidworks:overworld_void_displacer +setblock ~14 ~3 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"minecraft:coal_block",count:64}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/sign.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/sign.mcfunction new file mode 100644 index 0000000..b48e2c4 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/sign.mcfunction @@ -0,0 +1,3 @@ +# A scene's sign at ~14 ~ ~0, facing south, waxed. Its name is in bold, and clicking it runs the +# scene's function again from the plot's corner, 14 blocks west of the sign, which builds it afresh. +$setblock ~14 ~ ~ minecraft:oak_sign[rotation=0]{is_waxed:1b,front_text:{messages:[{translate:"voidworks.gallery.$(scene)",bold:true,click_event:{action:"run_command",command:"execute positioned ~-14 ~ ~ run function voidworks:gallery/$(scene)"}},{translate:"voidworks.gallery.$(scene).1"},{translate:"voidworks.gallery.$(scene).2"},{translate:"voidworks.gallery.$(scene).3"}]}} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/unmaking_chamber.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/unmaking_chamber.mcfunction new file mode 100644 index 0000000..b6cf8f2 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/unmaking_chamber.mcfunction @@ -0,0 +1,4 @@ +# The Unmaking Chamber: buckets broken down into their iron ingots, each by chance, for motes. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"unmaking_chamber"} +function voidworks:gallery/chamber {chamber:"unmaking_chamber",item:"minecraft:bucket",count:8} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction new file mode 100644 index 0000000..e1d0122 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction @@ -0,0 +1,8 @@ +# The Void Crucible: copper ingots upgraded to iron for free, slowly, fed from a hopper above and +# emptied by a hopper below into a chest. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"void_crucible"} +setblock ~14 ~1 ~-6 voidworks:void_crucible +setblock ~14 ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"minecraft:copper_ingot",count:4}]} +setblock ~14 ~ ~-6 minecraft:hopper[facing=south] +setblock ~14 ~ ~-5 minecraft:chest diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction index da2269f..afd98de 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction @@ -30,4 +30,4 @@ setblock ~20 ~2 ~-4 voidworks:void_well[facing=south] voidworks well ~20 ~2 ~-4 full voidworks dragon ~8 ~2 ~-4 -setblock ~14 ~ ~ minecraft:oak_sign[rotation=0]{front_text:{messages:[{translate:"voidworks.gallery.void_dragon",bold:true},{translate:"voidworks.gallery.void_dragon.1"},{translate:"voidworks.gallery.void_dragon.2"},{translate:"voidworks.gallery.void_dragon.3"}]}} +function voidworks:gallery/sign {scene:"void_dragon"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction new file mode 100644 index 0000000..ce28a77 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction @@ -0,0 +1,8 @@ +# The Void Siphon: a chest holding one, a full patch of Voidstone to charge it from and a bare one to +# empty it into, and a sign saying what to do. A player takes the Siphon; the scene gives nothing. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"void_siphon"} +fill ~7 ~ ~-8 ~9 ~ ~-6 voidworks:voidstone +fill ~19 ~ ~-8 ~21 ~ ~-6 voidworks:voidstone +voidworks mote ~8 ~ ~-7 5 +setblock ~14 ~ ~-3 minecraft:chest{Items:[{Slot:13b,id:"voidworks:void_siphon",count:1}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/voidstone_networks.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/voidstone_networks.mcfunction new file mode 100644 index 0000000..6d88850 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/voidstone_networks.mcfunction @@ -0,0 +1,8 @@ +# Voidstone networks: two lines of 16 Voidstone, apart. Motes put into the near end of one crawl +# along it, the whole line one network with room for 256; the other, touching nothing, stays empty. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"voidstone_networks"} +fill ~5 ~ ~-6 ~20 ~ ~-6 voidworks:voidstone +fill ~5 ~ ~-9 ~20 ~ ~-9 voidworks:voidstone +# One grade above the End's Void Pressure over the open void, worth something wherever it is built. +voidworks mote ~5 ~ ~-6 5 64 From ea084e4501eb6391c858cb45dcd9b1af6399a72a Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 10:58:58 +0200 Subject: [PATCH 3/7] fix: clear a replayed scene's plot on whole blocks, and check the gallery's displays and dormant chamber Co-Authored-By: Claude Opus 5.5 --- ...optional-gallery-pack-ahead-of-libworks.md | 2 +- .../voidworks/gametest/GalleryTests.java | 31 ++++++++++++++++++- .../function/gallery/clear.mcfunction | 4 +-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md b/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md index 61f2823..33e6f30 100644 --- a/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md +++ b/docs/adr/0008-voidworks-ships-an-optional-gallery-pack-ahead-of-libworks.md @@ -46,7 +46,7 @@ dragon kill bringing back the founder egg. with its `dragon remove`, so building it again leaves one dragon. - A scene is replayed from its own sign: a click event runs its function again, rebuilding it from the start, so a scene that runs out (a Displacer's harvests, a Dormant machine waking) can be - watched after `build` has laid out the whole row. A sign needs no setting, where a command block + watched after `build` has laid out the whole gallery. A sign needs no setting, where a command block is off on a server until `enable-command-block` is set, and the Gallery already needs an operator. - A function run from the server console has no player to own the scene's Wells and dragon, so the dragon scene fails there; it is for an operator player. diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java index 286a10c..f9e8136 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java @@ -13,6 +13,7 @@ import io.github._5thlayer.voidworks.Voidworks; import io.github._5thlayer.voidworks.VoidworksBlocks; import io.github._5thlayer.voidworks.VoidworksConfig; +import io.github._5thlayer.voidworks.dormant.Dormancy; import io.github._5thlayer.voidworks.network.MoteNetwork; import io.github._5thlayer.voidworks.network.VoidstoneNetworks; import io.github._5thlayer.voidworks.dragon.Place; @@ -32,6 +33,8 @@ import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.SignBlockEntity; +import net.minecraft.world.entity.Display; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.util.FakePlayer; @@ -48,6 +51,7 @@ final class GalleryTests { private static final Identifier BUILD = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/build"); private static final Identifier VOID_DRAGON = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/void_dragon"); private static final Identifier DENSITY = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/density"); + private static final Identifier DORMANT_MACHINES = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/dormant_machines"); private static final Identifier VOID_CRUCIBLE = Identifier.fromNamespaceAndPath(Voidworks.MOD_ID, "gallery/void_crucible"); /** How far east each scene's plot is of the one before it in its row, and how far north each row is of the last. */ @@ -84,6 +88,8 @@ static void register(VoidworksGameTests.Registrar tests) { GalleryTests::dragonCarries); tests.testOnItsOwn("the_gallery_density_scenes_displacers_each_yield_their_densitys_motes", TICKS, GalleryTests::densityYields); + tests.testOnItsOwn("the_gallery_dormant_machines_scenes_chamber_soaks_its_cost_and_wakes", TICKS, + GalleryTests::dormantWakes); tests.testOnItsOwn("the_gallery_scenes_sign_clicked_builds_the_scene_again", TICKS, GalleryTests::signReplays); } @@ -105,7 +111,7 @@ private static void builds(GameTestHelper helper) { Map.entry(SHORT, VoidworksBlocks.VOID_WELL.get()), Map.entry(scene(1, 14, 2, -6), VoidworksBlocks.OVERWORLD_DISPLACER.get()), // The game tests run in the Overworld, so the End and Nether scenes show - // their Displacers in a frame, behind their signs. + // their Displacers as item displays, over a pedestal behind their signs. Map.entry(scene(2, SIGN), Blocks.OAK_SIGN), Map.entry(scene(3, SIGN), Blocks.OAK_SIGN), Map.entry(scene(4, 20, 1, -6), VoidworksBlocks.OVERWORLD_DISPLACER.get()), @@ -115,6 +121,11 @@ private static void builds(GameTestHelper helper) { Map.entry(scene(8, 14, 1, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), Map.entry(scene(9, 14, 1, -6), VoidworksBlocks.UNMAKING_CHAMBER.get()), Map.entry(scene(10, 14, 1, -6), VoidworksBlocks.VOID_CRUCIBLE.get()))); + for (int index : new int[] {2, 3}) { + var over = helper.absolutePos(ORIGIN.offset(scene(index, 14, 1, -2))); + var shown = helper.getLevel().getEntitiesOfClass(Display.ItemDisplay.class, new AABB(over)); + helper.assertTrue(shown.size() == 1, "scene " + index + " shows " + shown.size() + " Displacers over its pedestal, not one"); + } off.set(clearAway(helper, source)); }) .thenWaitUntil(() -> assertOff(helper, off)) @@ -175,6 +186,24 @@ private static void densityYields(GameTestHelper helper) { .thenSucceed(); } + /** The Dormant machines scene: its Chamber soaks its cost from the motes along the line, and wakes. */ + private static void dormantWakes(GameTestHelper helper) { + var server = helper.getLevel().getServer(); + var source = operator(helper); + var chamber = helper.absolutePos(ORIGIN).offset(14, 0, -6); + clearAwayIfItFails(helper, source); + var on = GalleryCheck.select(server, GalleryPack.ID, true); + var off = new AtomicReference>(); + helper.startSequence() + .thenWaitUntil(() -> helper.assertTrue(on.isDone(), "the Gallery pack is not on yet")) + .thenExecute(() -> GalleryCheck.assertRuns(helper, source, DORMANT_MACHINES)) + .thenWaitUntil(() -> helper.assertTrue(helper.getLevel().getBlockEntity(chamber) instanceof Dormancy.Holder machine + && machine.dormancy().awake(), "the scene's Chamber is not awake yet")) + .thenExecute(() -> off.set(clearAway(helper, source))) + .thenWaitUntil(() -> assertOff(helper, off)) + .thenSucceed(); + } + /** A scene's sign, clicked, builds the scene again where it stands: here the Crucible, taken away. */ private static void signReplays(GameTestHelper helper) { var server = helper.getLevel().getServer(); diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction index 4dcb13f..6c1e112 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction @@ -1,7 +1,7 @@ # Clears a scene's plot, from ~2 to ~25 east and from ~-12 to ~0 south, 16 high, onto a smooth stone # floor, which no Displacer harvests: the item displays and dropped items in it, then its blocks. -execute positioned ~2 ~-1 ~-12 as @e[type=minecraft:item_display,dx=23,dy=16,dz=12] run kill @s -execute positioned ~2 ~-1 ~-12 as @e[type=minecraft:item,dx=23,dy=16,dz=12] run kill @s +execute align xyz positioned ~2 ~-1 ~-12 as @e[type=minecraft:item_display,dx=23,dy=16,dz=12] run kill @s +execute align xyz positioned ~2 ~-1 ~-12 as @e[type=minecraft:item,dx=23,dy=16,dz=12] run kill @s fill ~2 ~-1 ~-12 ~25 ~15 ~ minecraft:structure_void fill ~2 ~-1 ~-12 ~25 ~-1 ~ minecraft:smooth_stone fill ~2 ~ ~-12 ~25 ~15 ~ minecraft:air From 9de6381e0c65e55c566885ed2e87daa0c1ef7257 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 11:31:49 +0200 Subject: [PATCH 4/7] fix: make the gallery's scenes read in game Show the Density stones beside their Displacers with a framed block each, split the Siphon scene into charging and emptying, feed the Crucible and Chambers from the side, and stop a replay dropping its sign. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + .../voidworks/gametest/GalleryTests.java | 27 +++++++++++++------ .../assets/voidworks/lang/en_us.json | 12 ++++++--- .../function/gallery/build.mcfunction | 11 ++++---- .../function/gallery/chamber.mcfunction | 7 ++--- .../function/gallery/clear.mcfunction | 7 +++-- .../function/gallery/density.mcfunction | 4 +-- .../function/gallery/density/one.mcfunction | 16 ++++++----- .../function/gallery/void_crucible.mcfunction | 6 ++--- .../function/gallery/void_dragon.mcfunction | 6 ++--- .../function/gallery/void_siphon.mcfunction | 8 ------ .../gallery/void_siphon_charging.mcfunction | 8 ++++++ .../gallery/void_siphon_emptying.mcfunction | 6 +++++ 13 files changed, 73 insertions(+), 46 deletions(-) delete mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction create mode 100644 src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_emptying.mcfunction diff --git a/CHANGELOG.md b/CHANGELOG.md index 5311420..048c13b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Written for Consumers: what a mod building against Voidworks can use, or will se - With Groundworks present, a Void Well is placed in one step from its core: holding a core shows the whole Well in Groundworks' preview, and a click places the core, its 56 casing and 16 rim around an open shaft, paid from the inventory, all or nothing, the core facing out of its wall toward the player, so the Well is whole at once. Once placed it is an ordinary Well, and breaking a casing stops it as before. Without Groundworks nothing changes: it is built by hand. The Assembly is data alone, `data/voidworks/groundworks/assembly/void_well.json`, its core made a Key by the `groundworks:assembly_keys` block tag. Voidworks still requires nothing but Minecraft and NeoForge. (#65) - **Breaking:** a grown Void Dragon ages through four life stages, young, adult, senior and old, by the motes it unloads over its life, each stage `lifeStageMotes` (524,288) long, changing only at a stop (ADR 0010). Each stage multiplies its load and speed (`lifeStageLoads` 1/2/3.5/6, `lifeStageSpeeds` 1/0.6/0.35/0.2 in `voidworks-server.toml`), its speed stacking on its health's share, floored at a quarter; a new load applies from its next load and a new speed from its next dive. Only an adult lays Drained Dragon Eggs: eggs it still owes on turning senior are laid at its next loaded stop, then no more. An old dragon whose stage runs out dies at the end of a stop at a loaded Well, carrying nothing, living on past an unloaded one: it sets any rider down on the Well's rim, lays the eggs it owes, and its presence rises over the Well in a short Ender Dragon death, beams and sound, leaving nothing; nothing else tells its owner. An egg's price now counts its owner's living dragons and eggs soaking, not every dragon they ever hatched, so a death, or `/voidworks dragon remove`, lowers it (`Hatchery.lose`). `/voidworks dragon age ` sets the grown dragon an operator looks at to the start of that stage, owing no egg. Jade shows a dragon's stage, and its presence is sized ×0.8, ×1, ×1.1 or ×1.2 by it. Dragons saved before this start young, their count toward an egg dropped. `Routing` takes a `LifeStages` and `step` returns the dragons that died; `VoidDragonRecord` gains `cargo` and loses `speed()`, now `LifeStages.speed(dragon)`; `DragonReport` gains `stage`. (#54) - The Gallery pack builds a scene for each feature, in rows of three beside the Void Dragon's: the Overworld, End and Nether Displacers, Density, Voidstone networks, the Void Siphon, Dormant machines, the Mutation and Unmaking Chambers and the Void Crucible, each `voidworks:gallery/`. Clicking a scene's sign builds it again from the start. The End and Nether Displacers work only in their own dimension, so built anywhere else, as the Overworld's and Density's are outside the Overworld, their scene shows the Displacer as an item over a pedestal. (#77) +- The Gallery pack builds a scene for each feature, in rows of three beside the Void Dragon's: the Overworld, End and Nether Displacers, Density, Voidstone networks, charging and emptying the Void Siphon, Dormant machines, the Mutation and Unmaking Chambers and the Void Crucible, each `voidworks:gallery/`. Clicking a scene's sign builds it again from the start. The End and Nether Displacers work only in their own dimension, so built anywhere else, as the Overworld's and Density's are outside the Overworld, their scene shows the Displacer as an item over a pedestal. (#77) - **Breaking:** a dragon egg's price is datapack data, no longer server config (ADR 0009). The `voidworks:egg_price` block data map, on `voidworks:soaking_dragon_egg`, names an owner's `first_price` (25600 void energy) and its `growth` (2), the multiple each dragon they have hatched or are soaking puts on their next egg; a growth of 1 keeps every egg at the first price, and an egg with no entry is free. `firstEggPrice` is gone from `voidworks-server.toml` and `VoidworksConfig`. `EggPrice.of(dragons)` gives a price, `EggPrice.of(state)` an egg block's entry, and `Hatchery.startSoaking` takes the `EggPrice`; `Hatchery.price` and `Hatchery.codec` give way to `EggPrice.of` and `Hatchery.CODEC`. (#25) - A Void Dragon resting at a Well lands and sits astride its rim, over the shaft, lengthwise along the wall its core is set in so neither head nor tail covers the core, in the Ender Dragon's sitting pose, its wings held still and down, turning its head toward a nearby player. Where blocks fill the room its body takes there, it flies about over the shaft instead and lands once there is room. As it sets off it takes off, then dives into the shaft; mounted by its owner, it takes off to hover, and lands again once they get off. One at work at a Well, loading, unloading, waiting for its owner or setting a rider down, stays in the air, and one back after its chunk unloaded is sitting already. `VoidDragon.perch()` says whether a presence flies, lands, sits or takes off (`VoidDragon.Perch`), `perchYaw()` the heading it keeps meanwhile and `seatPos()` where it sits. A ridden dragon now hovers in place: before, its wandering pulled it slowly about under its rider. (#81) - A Void Dragon resting at a Well whose chunk is not loaded no longer loads that chunk each second to see whether to show it (ADR 0005). diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java index f9e8136..8000992 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java @@ -34,6 +34,8 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.entity.Display; +import net.minecraft.world.entity.decoration.ItemFrame; +import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.util.FakePlayer; @@ -60,7 +62,7 @@ final class GalleryTests { /** How many scenes a row holds. */ private static final int ROW = 3; /** How many scenes {@code build} lays, the Void Dragon's first. */ - private static final int SCENES = 11; + private static final int SCENES = 12; /** Where the gallery is run from: the platform's south-west corner, its plots spilling north and east of the platform. */ private static final BlockPos ORIGIN = new BlockPos(0, 1, 8); @@ -69,7 +71,7 @@ final class GalleryTests { private static final BlockPos SHORT = new BlockPos(20, 2, -4); /** Where a scene's sign stands, from where the scene is run. */ private static final BlockPos SIGN = new BlockPos(14, 0, 0); - /** The Density scene's four Displacers, from where it is run, coal's to diamond's, each over its one stone. */ + /** The Density scene's four Displacers, from where it is run, coal's to diamond's, each on its pad of Voidstone. */ private static final int[] DENSITY_XS = {5, 10, 15, 20}; /** A scene's plot, from where it is run, its floor included. */ private static final BlockPos PLOT_FROM = new BlockPos(2, -1, -12); @@ -116,11 +118,12 @@ private static void builds(GameTestHelper helper) { Map.entry(scene(3, SIGN), Blocks.OAK_SIGN), Map.entry(scene(4, 20, 1, -6), VoidworksBlocks.OVERWORLD_DISPLACER.get()), Map.entry(scene(5, 5, 0, -6), VoidworksBlocks.VOIDSTONE.get()), - Map.entry(scene(6, 14, 0, -3), Blocks.CHEST), - Map.entry(scene(7, 14, 0, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), - Map.entry(scene(8, 14, 1, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), - Map.entry(scene(9, 14, 1, -6), VoidworksBlocks.UNMAKING_CHAMBER.get()), - Map.entry(scene(10, 14, 1, -6), VoidworksBlocks.VOID_CRUCIBLE.get()))); + Map.entry(scene(6, 14, 0, -2), Blocks.CHEST), + Map.entry(scene(7, 14, 0, -2), Blocks.CHEST), + Map.entry(scene(8, 14, 0, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), + Map.entry(scene(9, 14, 1, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), + Map.entry(scene(10, 14, 1, -6), VoidworksBlocks.UNMAKING_CHAMBER.get()), + Map.entry(scene(11, 14, 1, -6), VoidworksBlocks.VOID_CRUCIBLE.get()))); for (int index : new int[] {2, 3}) { var over = helper.absolutePos(ORIGIN.offset(scene(index, 14, 1, -2))); var shown = helper.getLevel().getEntitiesOfClass(Display.ItemDisplay.class, new AABB(over)); @@ -161,7 +164,7 @@ private static void dragonCarries(GameTestHelper helper) { } /** - * The Density scene: each Displacer, fed one block, harvests the stone under it, so its network + * The Density scene: each Displacer, fed one block, harvests the stone beside it, so its network * holds the motes one harvest of that Density yields. */ private static void densityYields(GameTestHelper helper) { @@ -175,6 +178,10 @@ private static void densityYields(GameTestHelper helper) { .thenExecute(() -> GalleryCheck.assertRuns(helper, source, DENSITY)) .thenWaitUntil(() -> { for (int density = 1; density <= DENSITY_XS.length; density++) { + var face = helper.absolutePos(ORIGIN).offset(DENSITY_XS[density - 1], 1, -5); + var framed = helper.getLevel().getEntitiesOfClass(ItemFrame.class, new AABB(face)); + helper.assertTrue(framed.size() == 1 && !framed.getFirst().getItem().isEmpty(), + "Density " + density + "'s Displacer shows " + framed + " on its face, not one framed block"); var stone = helper.absolutePos(ORIGIN).offset(DENSITY_XS[density - 1], 0, -6); long motes = VoidstoneNetworks.of(helper.getLevel()).at(stone).map(MoteNetwork::total).orElse(0L); long yield = VoidworksConfig.motes(density); @@ -223,6 +230,9 @@ private static void signReplays(GameTestHelper helper) { "the scene's sign runs no command when clicked"); helper.assertTrue(helper.getLevel().getBlockState(crucible).is(VoidworksBlocks.VOID_CRUCIBLE.get()), "clicking the sign did not build the Crucible again where it stood"); + var plot = AABB.encapsulatingFullBlocks(helper.absolutePos(ORIGIN.offset(PLOT_FROM)), helper.absolutePos(ORIGIN.offset(PLOT_TO))); + var loose = helper.getLevel().getEntitiesOfClass(ItemEntity.class, plot); + helper.assertTrue(loose.isEmpty(), "building the scene again left items loose: " + loose.stream().map(ItemEntity::getItem).toList()); off.set(clearAway(helper, source)); }) .thenWaitUntil(() -> assertOff(helper, off)) @@ -280,6 +290,7 @@ private static CompletableFuture clearAway(GameTestHelper helper, CommandS commands.performPrefixedCommand(source, "fill " + box + " minecraft:air"); } commands.performPrefixedCommand(source, "kill @e[type=minecraft:item_display,distance=..200]"); + commands.performPrefixedCommand(source, "kill @e[type=minecraft:item_frame,distance=..200]"); forceLoad(helper, false); return GalleryCheck.select(helper.getLevel().getServer(), GalleryPack.ID, false); } diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index 744cb5d..0fcbf50 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -51,10 +51,14 @@ "voidworks.gallery.voidstone_networks.1": "touching Voidstone", "voidworks.gallery.voidstone_networks.2": "is one network:", "voidworks.gallery.voidstone_networks.3": "motes crawl", - "voidworks.gallery.void_siphon": "Void Siphon", - "voidworks.gallery.void_siphon.1": "take it, then", - "voidworks.gallery.void_siphon.2": "charge on the full", - "voidworks.gallery.void_siphon.3": "empty on the bare", + "voidworks.gallery.void_siphon_charging": "Charging a Siphon", + "voidworks.gallery.void_siphon_charging.1": "take it from", + "voidworks.gallery.void_siphon_charging.2": "the chest, stand", + "voidworks.gallery.void_siphon_charging.3": "on the Voidstone", + "voidworks.gallery.void_siphon_emptying": "Emptying a Siphon", + "voidworks.gallery.void_siphon_emptying.1": "take it from", + "voidworks.gallery.void_siphon_emptying.2": "the chest, stand", + "voidworks.gallery.void_siphon_emptying.3": "on the Voidstone", "voidworks.gallery.dormant_machines": "Dormant Machines", "voidworks.gallery.dormant_machines.1": "a Dormant Chamber", "voidworks.gallery.dormant_machines.2": "soaks its cost", diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction index 47d9d38..8b62917 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/build.mcfunction @@ -9,8 +9,9 @@ execute positioned ~48 ~ ~ run function voidworks:gallery/end_displacer execute positioned ~ ~ ~-16 run function voidworks:gallery/nether_displacer execute positioned ~24 ~ ~-16 run function voidworks:gallery/density execute positioned ~48 ~ ~-16 run function voidworks:gallery/voidstone_networks -execute positioned ~ ~ ~-32 run function voidworks:gallery/void_siphon -execute positioned ~24 ~ ~-32 run function voidworks:gallery/dormant_machines -execute positioned ~48 ~ ~-32 run function voidworks:gallery/mutation_chamber -execute positioned ~ ~ ~-48 run function voidworks:gallery/unmaking_chamber -execute positioned ~24 ~ ~-48 run function voidworks:gallery/void_crucible +execute positioned ~ ~ ~-32 run function voidworks:gallery/void_siphon_charging +execute positioned ~24 ~ ~-32 run function voidworks:gallery/void_siphon_emptying +execute positioned ~48 ~ ~-32 run function voidworks:gallery/dormant_machines +execute positioned ~ ~ ~-48 run function voidworks:gallery/mutation_chamber +execute positioned ~24 ~ ~-48 run function voidworks:gallery/unmaking_chamber +execute positioned ~48 ~ ~-48 run function voidworks:gallery/void_crucible diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction index 95ca57d..6359383 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction @@ -1,7 +1,8 @@ -# A Chamber's scene: the Chamber built awake, fed from a hopper above and emptied by a hopper below -# into a chest, with 18 Voidstone beside it full of motes to pay for its work. +# A Chamber's scene: the Chamber built awake, fed from a hopper on its east side, clear of what it +# shows over it, and emptied by a hopper below into a chest, with 18 Voidstone beside it full of +# motes to pay for its work. $setblock ~14 ~1 ~-6 voidworks:$(chamber)[dormant=false]{dormancy:{awake:1b}} -$setblock ~14 ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"$(item)",count:$(count)}]} +$setblock ~15 ~1 ~-6 minecraft:hopper[facing=west]{Items:[{Slot:0b,id:"$(item)",count:$(count)}]} setblock ~14 ~ ~-6 minecraft:hopper[facing=south] setblock ~14 ~ ~-5 minecraft:chest fill ~12 ~ ~-7 ~13 ~2 ~-5 voidworks:voidstone diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction index 6c1e112..bb5b350 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction @@ -1,7 +1,10 @@ # Clears a scene's plot, from ~2 to ~25 east and from ~-12 to ~0 south, 16 high, onto a smooth stone -# floor, which no Displacer harvests: the item displays and dropped items in it, then its blocks. +# floor, which no Displacer harvests: the item displays and item frames in it, then its blocks, then +# the items dropped, both those left lying and those the fills knock loose, such as the sign, whose +# floor goes before it does. execute align xyz positioned ~2 ~-1 ~-12 as @e[type=minecraft:item_display,dx=23,dy=16,dz=12] run kill @s -execute align xyz positioned ~2 ~-1 ~-12 as @e[type=minecraft:item,dx=23,dy=16,dz=12] run kill @s +execute align xyz positioned ~2 ~-1 ~-12 as @e[type=minecraft:item_frame,dx=23,dy=16,dz=12] run kill @s fill ~2 ~-1 ~-12 ~25 ~15 ~ minecraft:structure_void fill ~2 ~-1 ~-12 ~25 ~-1 ~ minecraft:smooth_stone fill ~2 ~ ~-12 ~25 ~15 ~ minecraft:air +execute align xyz positioned ~2 ~-1 ~-12 as @e[type=minecraft:item,dx=23,dy=16,dz=12] run kill @s diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction index fba0b2e..99c9180 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density.mcfunction @@ -1,6 +1,6 @@ # Density: four Overworld Displacers, each fed one block of a Density from coal to diamond, each -# harvesting the one stone under it into a network of four Voidstone around that stone, then turning -# to Voidstone itself. Jade on each network shows the motes its one harvest yielded: 1, 4, 16, 64. +# harvesting the one stone beside it into a pad of Voidstone under them, then turning to Voidstone +# itself. Jade on each network shows the motes its one harvest yielded: 1, 4, 16, 64. function voidworks:gallery/clear function voidworks:gallery/sign {scene:"density"} execute if dimension minecraft:overworld run function voidworks:gallery/density/one {x:5,block:"minecraft:coal_block"} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction index fe2fef4..9043daf 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction @@ -1,9 +1,11 @@ -# One Density's Displacer at ~x, the one stone under it ringed by four Voidstone: room for 80 motes, -# more than a diamond block's 64. -$setblock ~$(x) ~ ~-6 minecraft:stone -$setblock ~$(x) ~ ~-7 voidworks:voidstone -$setblock ~$(x) ~ ~-5 voidworks:voidstone -$execute positioned ~$(x) ~ ~-6 run setblock ~-1 ~ ~ voidworks:voidstone -$execute positioned ~$(x) ~ ~-6 run setblock ~1 ~ ~ voidworks:voidstone +# One Density's Displacer at ~x, its one stone beside it in plain sight, east, so its swap for +# Voidstone shows. Under both, a pad of six Voidstone the stone joins: room for 96 motes, more than a +# diamond block's 64, and apart from the next Density's pad. +$fill ~$(x) ~ ~-7 ~$(x) ~ ~-6 voidworks:voidstone +$execute positioned ~$(x) ~ ~-7 run fill ~1 ~ ~ ~2 ~ ~1 voidworks:voidstone $setblock ~$(x) ~1 ~-6 voidworks:overworld_void_displacer +$execute positioned ~$(x) ~1 ~-6 run setblock ~1 ~ ~ minecraft:stone $setblock ~$(x) ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"$(block)",count:1}]} +# The block it swaps in, framed on its south face, toward the sign. A frame's NBT names its block +# absolutely, which a function cannot, but the summon puts it where it is summoned once it is loaded. +$summon minecraft:item_frame ~$(x) ~1 ~-5 {Facing:3b,Fixed:1b,Invulnerable:1b,Item:{id:"$(block)",count:1}} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction index e1d0122..1c4686b 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_crucible.mcfunction @@ -1,8 +1,8 @@ -# The Void Crucible: copper ingots upgraded to iron for free, slowly, fed from a hopper above and -# emptied by a hopper below into a chest. +# The Void Crucible: copper ingots upgraded to iron for free, slowly, fed from a hopper on its east +# side, clear of the item it shows floating over it, and emptied by a hopper below into a chest. function voidworks:gallery/clear function voidworks:gallery/sign {scene:"void_crucible"} setblock ~14 ~1 ~-6 voidworks:void_crucible -setblock ~14 ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"minecraft:copper_ingot",count:4}]} +setblock ~15 ~1 ~-6 minecraft:hopper[facing=west]{Items:[{Slot:0b,id:"minecraft:copper_ingot",count:4}]} setblock ~14 ~ ~-6 minecraft:hopper[facing=south] setblock ~14 ~ ~-5 minecraft:chest diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction index afd98de..214704c 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction @@ -3,12 +3,10 @@ # whose target is full, and a grown dragon resting at the reservoir that carries between them, # diving into one shaft and emerging from the other. # -# The plot runs from ~2 to ~25 east and from ~-12 to the sign at ~0 south, 16 high on a stone floor. +# The plot runs from ~2 to ~25 east and from ~-12 to the sign at ~0 south, 16 high, cleared as every scene's is. # The dragons resting there or on a trip to or from it go first, so building it again leaves one. voidworks dragon remove ~2 ~-1 ~-12 ~25 ~15 ~ -fill ~2 ~-1 ~-12 ~25 ~15 ~ minecraft:structure_void -fill ~2 ~-1 ~-12 ~25 ~-1 ~ minecraft:stone -fill ~2 ~ ~-12 ~25 ~15 ~ minecraft:air +function voidworks:gallery/clear # The reservoir, its core in its south wall facing the sign, a Voidstone pillar against its west wall. fill ~6 ~ ~-8 ~10 ~3 ~-4 voidworks:void_well_casing diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction deleted file mode 100644 index ce28a77..0000000 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon.mcfunction +++ /dev/null @@ -1,8 +0,0 @@ -# The Void Siphon: a chest holding one, a full patch of Voidstone to charge it from and a bare one to -# empty it into, and a sign saying what to do. A player takes the Siphon; the scene gives nothing. -function voidworks:gallery/clear -function voidworks:gallery/sign {scene:"void_siphon"} -fill ~7 ~ ~-8 ~9 ~ ~-6 voidworks:voidstone -fill ~19 ~ ~-8 ~21 ~ ~-6 voidworks:voidstone -voidworks mote ~8 ~ ~-7 5 -setblock ~14 ~ ~-3 minecraft:chest{Items:[{Slot:13b,id:"voidworks:void_siphon",count:1}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction new file mode 100644 index 0000000..6abbc06 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction @@ -0,0 +1,8 @@ +# Charging the Void Siphon: a chest holding an empty one beside a patch of Voidstone full of motes. +# A player takes it and stands on the patch, and it charges from the network; the scene gives nothing. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"void_siphon_charging"} +fill ~12 ~ ~-8 ~16 ~ ~-4 voidworks:voidstone +# One grade above the End's Void Pressure over the open void, worth something wherever it is built. +voidworks mote ~14 ~ ~-6 5 +setblock ~14 ~ ~-2 minecraft:chest{Items:[{Slot:13b,id:"voidworks:void_siphon",count:1}]} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_emptying.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_emptying.mcfunction new file mode 100644 index 0000000..cef0b0d --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_emptying.mcfunction @@ -0,0 +1,6 @@ +# Emptying the Void Siphon: a chest holding one already charged and toggled to empty, beside a bare +# patch of Voidstone. A player takes it and stands on the patch, and it empties into the network. +function voidworks:gallery/clear +function voidworks:gallery/sign {scene:"void_siphon_emptying"} +fill ~12 ~ ~-8 ~16 ~ ~-4 voidworks:voidstone +setblock ~14 ~ ~-2 minecraft:chest{Items:[{Slot:13b,id:"voidworks:void_siphon",count:1,components:{"voidworks:siphon_motes":[{grade:5,count:32}],"voidworks:siphon_mode":"empty"}}]} From 52e9bd90c6fdfd15b5fb0f029d93c8087edc00cf Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 11:42:31 +0200 Subject: [PATCH 5/7] fix: fit the gallery's sign titles, and check the emptying scene's siphon Co-Authored-By: Claude Opus 5.5 --- .../voidworks/gametest/GalleryTests.java | 10 +++++++++ .../assets/voidworks/lang/en_us.json | 22 +++++++++---------- .../function/gallery/density/one.mcfunction | 8 +++---- .../function/gallery/end_displacer.mcfunction | 5 +++-- .../nether_displacer/working.mcfunction | 3 ++- .../function/gallery/void_dragon.mcfunction | 3 ++- .../gallery/void_siphon_charging.mcfunction | 3 ++- 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java index 8000992..8c2432c 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java @@ -13,6 +13,9 @@ import io.github._5thlayer.voidworks.Voidworks; import io.github._5thlayer.voidworks.VoidworksBlocks; import io.github._5thlayer.voidworks.VoidworksConfig; +import io.github._5thlayer.voidworks.VoidworksItems; +import io.github._5thlayer.voidworks.siphon.SiphonMode; +import io.github._5thlayer.voidworks.siphon.VoidSiphonItem; import io.github._5thlayer.voidworks.dormant.Dormancy; import io.github._5thlayer.voidworks.network.MoteNetwork; import io.github._5thlayer.voidworks.network.VoidstoneNetworks; @@ -30,8 +33,10 @@ import net.minecraft.resources.Identifier; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.permissions.PermissionSet; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.ChestBlockEntity; import net.minecraft.world.level.block.entity.SignBlockEntity; import net.minecraft.world.entity.Display; import net.minecraft.world.entity.decoration.ItemFrame; @@ -124,6 +129,11 @@ private static void builds(GameTestHelper helper) { Map.entry(scene(9, 14, 1, -6), VoidworksBlocks.MUTATION_CHAMBER.get()), Map.entry(scene(10, 14, 1, -6), VoidworksBlocks.UNMAKING_CHAMBER.get()), Map.entry(scene(11, 14, 1, -6), VoidworksBlocks.VOID_CRUCIBLE.get()))); + var emptying = helper.getLevel().getBlockEntity(helper.absolutePos(ORIGIN.offset(scene(7, 14, 0, -2)))); + var siphon = emptying instanceof ChestBlockEntity chest ? chest.getItem(13) : ItemStack.EMPTY; + helper.assertTrue(siphon.is(VoidworksItems.VOID_SIPHON.get()) && VoidSiphonItem.mode(siphon) == SiphonMode.EMPTY + && siphon.has(VoidworksItems.SIPHON_MOTES.get()), + "the Emptying scene's chest holds " + siphon + ", not a charged Siphon set to empty"); for (int index : new int[] {2, 3}) { var over = helper.absolutePos(ORIGIN.offset(scene(index, 14, 1, -2))); var shown = helper.getLevel().getEntitiesOfClass(Display.ItemDisplay.class, new AABB(over)); diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index 0fcbf50..964156f 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -31,15 +31,15 @@ "voidworks.gallery.void_dragon.1": "carries motes", "voidworks.gallery.void_dragon.2": "from a reservoir", "voidworks.gallery.void_dragon.3": "to a Well short", - "voidworks.gallery.overworld_displacer": "Overworld Displacer", + "voidworks.gallery.overworld_displacer": "Overworld", "voidworks.gallery.overworld_displacer.1": "swaps coal", "voidworks.gallery.overworld_displacer.2": "into stone and", "voidworks.gallery.overworld_displacer.3": "gives stone back", - "voidworks.gallery.end_displacer": "End Displacer", + "voidworks.gallery.end_displacer": "The End", "voidworks.gallery.end_displacer.1": "grows up", "voidworks.gallery.end_displacer.2": "into the air", "voidworks.gallery.end_displacer.3": "in the End only", - "voidworks.gallery.nether_displacer": "Nether Displacer", + "voidworks.gallery.nether_displacer": "The Nether", "voidworks.gallery.nether_displacer.1": "drinks lava", "voidworks.gallery.nether_displacer.2": "into its tank", "voidworks.gallery.nether_displacer.3": "in the Nether only", @@ -47,27 +47,27 @@ "voidworks.gallery.density.1": "coal to diamond:", "voidworks.gallery.density.2": "1, 4, 16 and 64", "voidworks.gallery.density.3": "motes a harvest", - "voidworks.gallery.voidstone_networks": "Voidstone Networks", + "voidworks.gallery.voidstone_networks": "Networks", "voidworks.gallery.voidstone_networks.1": "touching Voidstone", "voidworks.gallery.voidstone_networks.2": "is one network:", "voidworks.gallery.voidstone_networks.3": "motes crawl", - "voidworks.gallery.void_siphon_charging": "Charging a Siphon", + "voidworks.gallery.void_siphon_charging": "Charging", "voidworks.gallery.void_siphon_charging.1": "take it from", "voidworks.gallery.void_siphon_charging.2": "the chest, stand", "voidworks.gallery.void_siphon_charging.3": "on the Voidstone", - "voidworks.gallery.void_siphon_emptying": "Emptying a Siphon", - "voidworks.gallery.void_siphon_emptying.1": "take it from", - "voidworks.gallery.void_siphon_emptying.2": "the chest, stand", + "voidworks.gallery.void_siphon_emptying": "Emptying", + "voidworks.gallery.void_siphon_emptying.1": "a charged Siphon:", + "voidworks.gallery.void_siphon_emptying.2": "take it, stand", "voidworks.gallery.void_siphon_emptying.3": "on the Voidstone", - "voidworks.gallery.dormant_machines": "Dormant Machines", + "voidworks.gallery.dormant_machines": "Dormant", "voidworks.gallery.dormant_machines.1": "a Dormant Chamber", "voidworks.gallery.dormant_machines.2": "soaks its cost", "voidworks.gallery.dormant_machines.3": "and wakes", - "voidworks.gallery.mutation_chamber": "Mutation Chamber", + "voidworks.gallery.mutation_chamber": "Mutation", "voidworks.gallery.mutation_chamber.1": "upgrades copper", "voidworks.gallery.mutation_chamber.2": "to iron,", "voidworks.gallery.mutation_chamber.3": "for motes", - "voidworks.gallery.unmaking_chamber": "Unmaking Chamber", + "voidworks.gallery.unmaking_chamber": "Unmaking", "voidworks.gallery.unmaking_chamber.1": "breaks buckets", "voidworks.gallery.unmaking_chamber.2": "into iron,", "voidworks.gallery.unmaking_chamber.3": "for motes", diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction index 9043daf..841aaea 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction @@ -1,11 +1,11 @@ # One Density's Displacer at ~x, its one stone beside it in plain sight, east, so its swap for -# Voidstone shows. Under both, a pad of six Voidstone the stone joins: room for 96 motes, more than a -# diamond block's 64, and apart from the next Density's pad. +# Voidstone shows. Under both, a pad of six Voidstone the stone joins: room for 96 motes, more than +# a diamond block's 64, and apart from the next Density's pad. $fill ~$(x) ~ ~-7 ~$(x) ~ ~-6 voidworks:voidstone $execute positioned ~$(x) ~ ~-7 run fill ~1 ~ ~ ~2 ~ ~1 voidworks:voidstone $setblock ~$(x) ~1 ~-6 voidworks:overworld_void_displacer $execute positioned ~$(x) ~1 ~-6 run setblock ~1 ~ ~ minecraft:stone $setblock ~$(x) ~2 ~-6 minecraft:hopper[facing=down]{Items:[{Slot:0b,id:"$(block)",count:1}]} -# The block it swaps in, framed on its south face, toward the sign. A frame's NBT names its block -# absolutely, which a function cannot, but the summon puts it where it is summoned once it is loaded. +# The block it swaps in, framed on its south face, toward the sign. The frame has no block_pos, +# which takes absolute coordinates only: loading it logs an error, then summon places it here. $summon minecraft:item_frame ~$(x) ~1 ~-5 {Facing:3b,Fixed:1b,Invulnerable:1b,Item:{id:"$(block)",count:1}} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction index bfec006..2680e8b 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction @@ -1,5 +1,6 @@ -# The End Displacer: one awake, facing up, fed coal blocks from a hopper beside it. It grows its body -# of Voidstone up into the air until its harvests are spent. Outside the End it is shown as an item. +# The End Displacer: one awake, facing up, fed coal blocks from a hopper beside it. It grows its +# body of Voidstone up into the air until its harvests are spent. Outside the End it is shown as an +# item. function voidworks:gallery/clear function voidworks:gallery/sign {scene:"end_displacer"} execute if dimension minecraft:the_end run function voidworks:gallery/end_displacer/working diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction index 1042f41..ebf321e 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction @@ -1,4 +1,5 @@ -# The pool's wall holds the lava on the floor; the Displacer, built awake, takes the wall's east side. +# The pool's wall holds the lava on the floor; the Displacer, built awake, takes the wall's east +# side. fill ~10 ~ ~-8 ~14 ~ ~-4 minecraft:smooth_stone fill ~11 ~ ~-7 ~13 ~ ~-5 minecraft:lava setblock ~14 ~ ~-6 voidworks:nether_void_displacer[dormant=false]{dormancy:{awake:1b}} diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction index 214704c..436f19c 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction @@ -3,7 +3,8 @@ # whose target is full, and a grown dragon resting at the reservoir that carries between them, # diving into one shaft and emerging from the other. # -# The plot runs from ~2 to ~25 east and from ~-12 to the sign at ~0 south, 16 high, cleared as every scene's is. +# The plot runs from ~2 to ~25 east and from ~-12 to the sign at ~0 south, 16 high, cleared as +# every scene's is. # The dragons resting there or on a trip to or from it go first, so building it again leaves one. voidworks dragon remove ~2 ~-1 ~-12 ~25 ~15 ~ function voidworks:gallery/clear diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction index 6abbc06..dfb9c20 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction @@ -1,5 +1,6 @@ # Charging the Void Siphon: a chest holding an empty one beside a patch of Voidstone full of motes. -# A player takes it and stands on the patch, and it charges from the network; the scene gives nothing. +# A player takes it and stands on the patch, and it charges from the network; the scene gives +# nothing. function voidworks:gallery/clear function voidworks:gallery/sign {scene:"void_siphon_charging"} fill ~12 ~ ~-8 ~16 ~ ~-4 voidworks:voidstone From f6748560545965b85e53187f3c4f2df38aa1674c Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 11:51:28 +0200 Subject: [PATCH 6/7] fix: fit the gallery's last long sign lines, and check the emptying siphon holds motes Co-Authored-By: Claude Opus 5.5 --- .../_5thlayer/voidworks/gametest/GalleryTests.java | 10 +++++----- src/main/resources/assets/voidworks/lang/en_us.json | 10 +++++----- .../voidworks/function/gallery/void_dragon.mcfunction | 3 ++- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java index 8c2432c..87a4aaf 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java @@ -14,16 +14,16 @@ import io.github._5thlayer.voidworks.VoidworksBlocks; import io.github._5thlayer.voidworks.VoidworksConfig; import io.github._5thlayer.voidworks.VoidworksItems; -import io.github._5thlayer.voidworks.siphon.SiphonMode; -import io.github._5thlayer.voidworks.siphon.VoidSiphonItem; import io.github._5thlayer.voidworks.dormant.Dormancy; -import io.github._5thlayer.voidworks.network.MoteNetwork; -import io.github._5thlayer.voidworks.network.VoidstoneNetworks; import io.github._5thlayer.voidworks.dragon.Place; import io.github._5thlayer.voidworks.dragon.SavedVoidDragons; import io.github._5thlayer.voidworks.dragon.Trip; import io.github._5thlayer.voidworks.dragon.VoidDragonRecord; import io.github._5thlayer.voidworks.gallery.GalleryPack; +import io.github._5thlayer.voidworks.network.MoteNetwork; +import io.github._5thlayer.voidworks.network.VoidstoneNetworks; +import io.github._5thlayer.voidworks.siphon.SiphonMode; +import io.github._5thlayer.voidworks.siphon.VoidSiphonItem; import net.minecraft.commands.CommandSourceStack; import net.minecraft.core.BlockPos; import net.minecraft.gametest.framework.GameTestHelper; @@ -132,7 +132,7 @@ private static void builds(GameTestHelper helper) { var emptying = helper.getLevel().getBlockEntity(helper.absolutePos(ORIGIN.offset(scene(7, 14, 0, -2)))); var siphon = emptying instanceof ChestBlockEntity chest ? chest.getItem(13) : ItemStack.EMPTY; helper.assertTrue(siphon.is(VoidworksItems.VOID_SIPHON.get()) && VoidSiphonItem.mode(siphon) == SiphonMode.EMPTY - && siphon.has(VoidworksItems.SIPHON_MOTES.get()), + && VoidSiphonItem.heldMotes(siphon).total() > 0, "the Emptying scene's chest holds " + siphon + ", not a charged Siphon set to empty"); for (int index : new int[] {2, 3}) { var over = helper.absolutePos(ORIGIN.offset(scene(index, 14, 1, -2))); diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index 964156f..12a983b 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -38,18 +38,18 @@ "voidworks.gallery.end_displacer": "The End", "voidworks.gallery.end_displacer.1": "grows up", "voidworks.gallery.end_displacer.2": "into the air", - "voidworks.gallery.end_displacer.3": "in the End only", + "voidworks.gallery.end_displacer.3": "End only", "voidworks.gallery.nether_displacer": "The Nether", "voidworks.gallery.nether_displacer.1": "drinks lava", "voidworks.gallery.nether_displacer.2": "into its tank", - "voidworks.gallery.nether_displacer.3": "in the Nether only", + "voidworks.gallery.nether_displacer.3": "Nether only", "voidworks.gallery.density": "Density", "voidworks.gallery.density.1": "coal to diamond:", "voidworks.gallery.density.2": "1, 4, 16 and 64", "voidworks.gallery.density.3": "motes a harvest", "voidworks.gallery.voidstone_networks": "Networks", - "voidworks.gallery.voidstone_networks.1": "touching Voidstone", - "voidworks.gallery.voidstone_networks.2": "is one network:", + "voidworks.gallery.voidstone_networks.1": "touching blocks", + "voidworks.gallery.voidstone_networks.2": "are one network:", "voidworks.gallery.voidstone_networks.3": "motes crawl", "voidworks.gallery.void_siphon_charging": "Charging", "voidworks.gallery.void_siphon_charging.1": "take it from", @@ -60,7 +60,7 @@ "voidworks.gallery.void_siphon_emptying.2": "take it, stand", "voidworks.gallery.void_siphon_emptying.3": "on the Voidstone", "voidworks.gallery.dormant_machines": "Dormant", - "voidworks.gallery.dormant_machines.1": "a Dormant Chamber", + "voidworks.gallery.dormant_machines.1": "the Chamber", "voidworks.gallery.dormant_machines.2": "soaks its cost", "voidworks.gallery.dormant_machines.3": "and wakes", "voidworks.gallery.mutation_chamber": "Mutation", diff --git a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction index 436f19c..4b26b22 100644 --- a/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_dragon.mcfunction @@ -9,7 +9,8 @@ voidworks dragon remove ~2 ~-1 ~-12 ~25 ~15 ~ function voidworks:gallery/clear -# The reservoir, its core in its south wall facing the sign, a Voidstone pillar against its west wall. +# The reservoir, its core in its south wall facing the sign, a Voidstone pillar against its west +# wall. fill ~6 ~ ~-8 ~10 ~3 ~-4 voidworks:void_well_casing fill ~7 ~1 ~-7 ~9 ~3 ~-5 minecraft:air fill ~6 ~4 ~-8 ~10 ~4 ~-4 voidworks:void_well_rim From d0c8aaca8a51b396bf5ac4f8fd977f82aa61f0c8 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 11:52:45 +0200 Subject: [PATCH 7/7] fix: name voidstone on the gallery's networks sign Co-Authored-By: Claude Opus 5.5 --- src/main/resources/assets/voidworks/lang/en_us.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index 12a983b..6059189 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -48,8 +48,8 @@ "voidworks.gallery.density.2": "1, 4, 16 and 64", "voidworks.gallery.density.3": "motes a harvest", "voidworks.gallery.voidstone_networks": "Networks", - "voidworks.gallery.voidstone_networks.1": "touching blocks", - "voidworks.gallery.voidstone_networks.2": "are one network:", + "voidworks.gallery.voidstone_networks.1": "Voidstone that", + "voidworks.gallery.voidstone_networks.2": "touches is one:", "voidworks.gallery.voidstone_networks.3": "motes crawl", "voidworks.gallery.void_siphon_charging": "Charging", "voidworks.gallery.void_siphon_charging.1": "take it from",