diff --git a/CHANGELOG.md b/CHANGELOG.md index ca50c91..048c13b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ 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/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..c33312e 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. 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/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..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 @@ -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 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 b2861c4..87a4aaf 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/GalleryTests.java @@ -12,11 +12,18 @@ 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.VoidworksItems; +import io.github._5thlayer.voidworks.dormant.Dormancy; 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; @@ -26,6 +33,15 @@ 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; +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; @@ -41,13 +57,28 @@ 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. */ + 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 = 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); /** 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 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); private static final BlockPos PLOT_TO = new BlockPos(25, 15, 0); @@ -62,12 +93,19 @@ 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_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); } 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 +113,32 @@ 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 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()), + Map.entry(scene(5, 5, 0, -6), VoidworksBlocks.VOIDSTONE.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()))); + 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 + && 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))); + 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)) @@ -111,6 +173,105 @@ private static void dragonCarries(GameTestHelper helper) { .thenSucceed(); } + /** + * 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) { + 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 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); + helper.assertTrue(motes == yield, "Density " + density + "'s network holds " + motes + " motes, not " + yield); + } + }) + .thenExecute(() -> off.set(clearAway(helper, source))) + .thenWaitUntil(() -> assertOff(helper, off)) + .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(); + 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"); + 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)) + .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 +291,17 @@ 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]"); + 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 dedecbd..6059189 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -31,6 +31,50 @@ "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", + "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": "The End", + "voidworks.gallery.end_displacer.1": "grows up", + "voidworks.gallery.end_displacer.2": "into the air", + "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": "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": "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", + "voidworks.gallery.void_siphon_charging.2": "the chest, stand", + "voidworks.gallery.void_siphon_charging.3": "on the Voidstone", + "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", + "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", + "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", + "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..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 @@ -1,5 +1,17 @@ # 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_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 new file mode 100644 index 0000000..6359383 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/chamber.mcfunction @@ -0,0 +1,9 @@ +# 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 ~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 +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..bb5b350 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/clear.mcfunction @@ -0,0 +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 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_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 new file mode 100644 index 0000000..99c9180 --- /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 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"} +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..841aaea --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/density/one.mcfunction @@ -0,0 +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. +$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. 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/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..2680e8b --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/end_displacer.mcfunction @@ -0,0 +1,7 @@ +# 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..ebf321e --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/nether_displacer/working.mcfunction @@ -0,0 +1,6 @@ +# 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..1c4686b --- /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 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 ~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 da2269f..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 @@ -3,14 +3,14 @@ # 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. +# 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 @@ -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_charging.mcfunction b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction new file mode 100644 index 0000000..dfb9c20 --- /dev/null +++ b/src/main/resources/gallery_pack/data/voidworks/function/gallery/void_siphon_charging.mcfunction @@ -0,0 +1,9 @@ +# 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"}}]} 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