From 9f7f90946c04a5a826fdf5f631351e138d4d1c39 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 19:10:42 +0200 Subject: [PATCH 1/5] feat: show a block's density in its item tooltip An item a Density tag names shows one grey line under its name: its Density and the motes one yields in a Displacer, from the server's densityMotes. Before a world loads the config it shows the Density alone; an item of Density 0 shows nothing. Closes #106 Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + docs/spec/void-energy.md | 4 +- .../github/_5thlayer/voidworks/Voidworks.java | 4 +- .../voidworks/displacer/DensityTooltip.java | 38 ++++++++++++ .../gametest/DensityTooltipTests.java | 58 +++++++++++++++++++ .../gametest/VoidworksGameTests.java | 1 + .../assets/voidworks/lang/en_us.json | 2 + 7 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java create mode 100644 src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java diff --git a/CHANGELOG.md b/CHANGELOG.md index d7207e3..58be70b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Written for Consumers: what a mod building against Voidworks can use, or will se ## Unreleased +- An item a Density tag names shows its Density in its tooltip, right under its name, with the motes one yields fed to a Void Displacer, from `densityMotes` in `voidworks-server.toml` ("Density 4: 64 motes"), or its Density alone before a world has loaded the config. Another mod's storage blocks in the `c:` tags show it too; an item of Density 0 shows nothing. (#106) - A Void Dragon's rider watches it start down into the Well after they jump, sitting on its back as before, and sees the void only half a second after their eyes go below the Well's rim into the shaft (`VoidDragon.VOID_DELAY_TICKS`), the dragon diving on meanwhile; before, the screen went black as they jumped, while the dragon still hovered over the Well. They are unseen from the jump on, now from the jump's own tick. `VoidDragon.inTheVoid()` says whether a presence has taken its rider into the shaft, and its rider stands at its feet only from then; `carrying()` and `DragonRiding.inTheDive` still hold from the jump. (#84) - A Void Dragon is seen again wherever it is after its presence's chunk unloaded: that presence, never saved, was left out of the world but still counted as the dragon's, so no new one showed, at the Well it was called to or anywhere else, and it came back at its old place with the chunk. A presence where nothing ticks is now taken away, and a new one shows where its dragon is. (#79) - A grown Void Dragon with nothing to do away from its owner's Wells, such as one just grown from a Dragonling, dives to the nearest of them and rests there, so it can be ridden and called. Before, one with no trip to make stayed where it grew up for good. (#79) diff --git a/docs/spec/void-energy.md b/docs/spec/void-energy.md index a74fc26..a2b8f38 100644 --- a/docs/spec/void-energy.md +++ b/docs/spec/void-energy.md @@ -157,7 +157,9 @@ it, and it leaves no Voidstone: the renewable and abundant blocks above all (cob deepslate, dirt, sand, gravel, netherrack, blackstone, basalt, end stone, obsidian, snow, ice), and everything made from them, so a generator never feeds a harvest. Density rises steeply (shape: about 4^(density − 1), so 1, 4, 16, 64). Density tags and Families are separate data and need not agree: -amethyst, quartz and glowstone climb the gem and dust Families but stay Density 0, being renewable. +amethyst, quartz and glowstone climb the gem and dust Families but stay Density 0, being renewable. A +block item's tooltip shows its Density and the motes one yields in a Displacer; one of Density 0 +shows nothing. | Density | Motes | Blocks, raw and refined alike | |---|---|---| diff --git a/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java b/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java index a06b596..84bacea 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java +++ b/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java @@ -5,6 +5,7 @@ import io.github._5thlayer.voidworks.butterfly.VoidworksButterflies; import io.github._5thlayer.voidworks.command.VoidworksCommands; +import io.github._5thlayer.voidworks.displacer.DensityTooltip; import io.github._5thlayer.voidworks.displacer.Displacement; import io.github._5thlayer.voidworks.displacer.ZoneUpgrade; import io.github._5thlayer.voidworks.dormant.Dormancy; @@ -30,7 +31,7 @@ /** * The Module's entry point. It registers the Void Pressure data map (and checks the defaults it * ships), Voidstone and the Void Displacers with their displacement table and server - * config, the Dormant machines' cost map, conduction through Voidstone networks, the Families, the Unmaking Chamber's breakdown map, the + * config, the Density line in a fed block's tooltip, the Dormant machines' cost map, conduction through Voidstone networks, the Families, the Unmaking Chamber's breakdown map, the * Void Siphon, the dragon eggs, the Dragonling they hatch and the Void Dragon it grows into, which carries motes between Void Wells, the {@code /voidworks} commands and the game tests, which exist only when game tests * are enabled. */ @@ -50,6 +51,7 @@ public Voidworks(IEventBus modBus, ModContainer container) { VoidworksEntities.register(modBus); modBus.addListener(WorksTabContents::add); Displacement.register(modBus); + NeoForge.EVENT_BUS.addListener(DensityTooltip::onItemTooltip); Dormancy.register(modBus); DiveColour.register(modBus); EggPrice.register(modBus); diff --git a/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java b/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java new file mode 100644 index 0000000..2bb7796 --- /dev/null +++ b/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2026 5thlayer +// SPDX-License-Identifier: MIT + +package io.github._5thlayer.voidworks.displacer; + +import io.github._5thlayer.voidworks.VoidworksConfig; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; +import net.neoforged.neoforge.transfer.item.ItemResource; + +/** + * The line under the name of an item a Density tag names: its Density and, once the server's config + * is known, the motes one yields fed to a Void Displacer. An item of Density 0 shows nothing. + */ +public final class DensityTooltip { + + private DensityTooltip() { + } + + /** Puts {@code event}'s item's Density line right under its name, when it has a Density. */ + public static void onItemTooltip(ItemTooltipEvent event) { + int density = Density.of(ItemResource.of(event.getItemStack())); + if (density > 0) { + event.getToolTip().add(1, line(density)); + } + } + + /** @return the line an item of {@code density}, above 0, shows */ + private static Component line(int density) { + // Known on a client only once a server has sent its config. + if (!VoidworksConfig.loaded()) { + return Component.translatable("voidworks.density.tooltip", density).withStyle(ChatFormatting.GRAY); + } + return Component.translatable("voidworks.density.tooltip.motes", density, VoidworksConfig.motes(density)) + .withStyle(ChatFormatting.GRAY); + } +} diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java new file mode 100644 index 0000000..7c98f49 --- /dev/null +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2026 5thlayer +// SPDX-License-Identifier: MIT + +package io.github._5thlayer.voidworks.gametest; + +import java.util.List; + +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.contents.TranslatableContents; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.GameType; + +/** + * A fed block's Density in its tooltip, built on a real server with the server's config: the line + * under a Density item's name, with the motes a Displacer yields from it, and no line for a block of + * Density 0. + */ +final class DensityTooltipTests { + + private static final String LINE = "voidworks.density.tooltip.motes"; + + private DensityTooltipTests() { + } + + static void register(VoidworksGameTests.Registrar tests) { + tests.test("density_tooltip_shows_a_diamond_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.DIAMOND_BLOCK, 4, 64)); + tests.test("density_tooltip_shows_a_copper_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.COPPER_BLOCK, 1, 1)); + tests.test("density_tooltip_shows_nothing_for_cobblestone", 1, DensityTooltipTests::showsNothingForDensityZero); + } + + private static void showsUnderTheName(GameTestHelper helper, Item item, int density, int motes) { + var lines = tooltip(helper, item); + if (lines.size() < 2 || !(lines.get(1).getContents() instanceof TranslatableContents line) || !LINE.equals(line.getKey()) + || !List.of(density, motes).equals(List.of(line.getArgs()))) { + helper.fail(item + " should show Density " + density + " and " + motes + " motes right under its name, showed " + lines); + return; + } + helper.succeed(); + } + + private static void showsNothingForDensityZero(GameTestHelper helper) { + var lines = tooltip(helper, Items.COBBLESTONE); + if (lines.stream().anyMatch(c -> c.getContents() instanceof TranslatableContents line && line.getKey().startsWith("voidworks.density."))) { + helper.fail("cobblestone, of Density 0, showed a Density line: " + lines); + return; + } + helper.succeed(); + } + + private static List tooltip(GameTestHelper helper, Item item) { + return new ItemStack(item).getTooltipLines(Item.TooltipContext.of(helper.getLevel()), helper.makeMockPlayer(GameType.SURVIVAL), + TooltipFlag.NORMAL); + } +} diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/VoidworksGameTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/VoidworksGameTests.java index 6160dca..722f116 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/VoidworksGameTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/VoidworksGameTests.java @@ -76,6 +76,7 @@ private static void registerTests(RegisterGameTestsEvent event) { CommandTests.register(tests); ConductionTests.register(tests); CreativeTabTests.register(tests); + DensityTooltipTests.register(tests); DisplacerTests.register(tests); DormantTests.register(tests); DragonlingTests.register(tests); diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index 2e32c25..7e1c416 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -92,6 +92,8 @@ "item.voidworks.draconic_void_siphon": "Draconic Void Siphon", "item.voidworks.resonant_void_siphon": "Resonant Void Siphon", "item.voidworks.void_siphon": "Void Siphon", + "voidworks.density.tooltip": "Density %s", + "voidworks.density.tooltip.motes": "Density %s: %s motes", "voidworks.displacer.upgrade.cancel": "Upgrading: %s of %s void energy paid. Sneak-use again to cancel", "voidworks.displacer.upgrade.cancelled": "Zone upgrade cancelled", "voidworks.displacer.upgrade.committed": "Upgrading: Zone %s → %s once %s void energy is soaked", From 3b2c2451728314ac9c0a363512f9e00f4a6792ed Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 19:31:30 +0200 Subject: [PATCH 2/5] fix: say one mote as one in a block's density tooltip A Density 1 block read "Density 1: 1 motes"; it now reads "1 mote". The line is built from its Density and the motes when known, unit-tested, and DensityTooltip registers its own listener. Co-Authored-By: Claude Opus 5.5 --- .../github/_5thlayer/voidworks/Voidworks.java | 12 +++--- .../voidworks/displacer/DensityTooltip.java | 35 ++++++++++++----- .../gametest/DensityTooltipTests.java | 10 ++--- .../assets/voidworks/lang/en_us.json | 1 + .../displacer/DensityTooltipTest.java | 38 +++++++++++++++++++ 5 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java diff --git a/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java b/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java index 84bacea..37f801a 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java +++ b/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java @@ -30,10 +30,12 @@ /** * The Module's entry point. It registers the Void Pressure data map (and checks the defaults it - * ships), Voidstone and the Void Displacers with their displacement table and server - * config, the Density line in a fed block's tooltip, the Dormant machines' cost map, conduction through Voidstone networks, the Families, the Unmaking Chamber's breakdown map, the - * Void Siphon, the dragon eggs, the Dragonling they hatch and the Void Dragon it grows into, which carries motes between Void Wells, the {@code /voidworks} commands and the game tests, which exist only when game tests - * are enabled. + * ships), Voidstone and the Void Displacers with their displacement table and server config, the + * Density line in a fed block's tooltip, the Dormant machines' cost map, conduction through + * Voidstone networks, the Families, the Unmaking Chamber's breakdown map, the Void Siphon, the + * dragon eggs, the Dragonling they hatch and the Void Dragon it grows into, which carries motes + * between Void Wells, the {@code /voidworks} commands and the game tests, which exist only when + * game tests are enabled. */ @Mod(Voidworks.MOD_ID) public final class Voidworks { @@ -51,7 +53,7 @@ public Voidworks(IEventBus modBus, ModContainer container) { VoidworksEntities.register(modBus); modBus.addListener(WorksTabContents::add); Displacement.register(modBus); - NeoForge.EVENT_BUS.addListener(DensityTooltip::onItemTooltip); + DensityTooltip.register(); Dormancy.register(modBus); DiveColour.register(modBus); EggPrice.register(modBus); diff --git a/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java b/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java index 2bb7796..f287b77 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java +++ b/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java @@ -3,9 +3,12 @@ package io.github._5thlayer.voidworks.displacer; +import java.util.OptionalInt; + import io.github._5thlayer.voidworks.VoidworksConfig; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; +import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import net.neoforged.neoforge.transfer.item.ItemResource; @@ -18,21 +21,33 @@ public final class DensityTooltip { private DensityTooltip() { } - /** Puts {@code event}'s item's Density line right under its name, when it has a Density. */ - public static void onItemTooltip(ItemTooltipEvent event) { + /** Adds the line to every item tooltip built, which only a client builds outside the game tests. */ + public static void register() { + NeoForge.EVENT_BUS.addListener(DensityTooltip::onItemTooltip); + } + + private static void onItemTooltip(ItemTooltipEvent event) { int density = Density.of(ItemResource.of(event.getItemStack())); if (density > 0) { - event.getToolTip().add(1, line(density)); + // Known on a client only once a server has sent its config. + var motes = VoidworksConfig.loaded() ? OptionalInt.of(VoidworksConfig.motes(density)) : OptionalInt.empty(); + event.getToolTip().add(1, line(density, motes)); } } - /** @return the line an item of {@code density}, above 0, shows */ - private static Component line(int density) { - // Known on a client only once a server has sent its config. - if (!VoidworksConfig.loaded()) { - return Component.translatable("voidworks.density.tooltip", density).withStyle(ChatFormatting.GRAY); + /** + * @param motes what one yields fed to a Displacer, or empty when that is not known + * @return the line an item of {@code density}, above 0, shows + */ + static Component line(int density, OptionalInt motes) { + Component line; + if (motes.isEmpty()) { + line = Component.translatable("voidworks.density.tooltip", density); + } else if (motes.getAsInt() == 1) { + line = Component.translatable("voidworks.density.tooltip.mote", density, 1); + } else { + line = Component.translatable("voidworks.density.tooltip.motes", density, motes.getAsInt()); } - return Component.translatable("voidworks.density.tooltip.motes", density, VoidworksConfig.motes(density)) - .withStyle(ChatFormatting.GRAY); + return line.copy().withStyle(ChatFormatting.GRAY); } } diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java index 7c98f49..d0849bc 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java @@ -21,20 +21,18 @@ */ final class DensityTooltipTests { - private static final String LINE = "voidworks.density.tooltip.motes"; - private DensityTooltipTests() { } static void register(VoidworksGameTests.Registrar tests) { - tests.test("density_tooltip_shows_a_diamond_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.DIAMOND_BLOCK, 4, 64)); - tests.test("density_tooltip_shows_a_copper_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.COPPER_BLOCK, 1, 1)); + tests.test("density_tooltip_shows_a_diamond_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.DIAMOND_BLOCK, "voidworks.density.tooltip.motes", 4, 64)); + tests.test("density_tooltip_shows_a_copper_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.COPPER_BLOCK, "voidworks.density.tooltip.mote", 1, 1)); tests.test("density_tooltip_shows_nothing_for_cobblestone", 1, DensityTooltipTests::showsNothingForDensityZero); } - private static void showsUnderTheName(GameTestHelper helper, Item item, int density, int motes) { + private static void showsUnderTheName(GameTestHelper helper, Item item, String key, int density, int motes) { var lines = tooltip(helper, item); - if (lines.size() < 2 || !(lines.get(1).getContents() instanceof TranslatableContents line) || !LINE.equals(line.getKey()) + if (lines.size() < 2 || !(lines.get(1).getContents() instanceof TranslatableContents line) || !key.equals(line.getKey()) || !List.of(density, motes).equals(List.of(line.getArgs()))) { helper.fail(item + " should show Density " + density + " and " + motes + " motes right under its name, showed " + lines); return; diff --git a/src/main/resources/assets/voidworks/lang/en_us.json b/src/main/resources/assets/voidworks/lang/en_us.json index 7e1c416..2ce6c21 100644 --- a/src/main/resources/assets/voidworks/lang/en_us.json +++ b/src/main/resources/assets/voidworks/lang/en_us.json @@ -93,6 +93,7 @@ "item.voidworks.resonant_void_siphon": "Resonant Void Siphon", "item.voidworks.void_siphon": "Void Siphon", "voidworks.density.tooltip": "Density %s", + "voidworks.density.tooltip.mote": "Density %s: %s mote", "voidworks.density.tooltip.motes": "Density %s: %s motes", "voidworks.displacer.upgrade.cancel": "Upgrading: %s of %s void energy paid. Sneak-use again to cancel", "voidworks.displacer.upgrade.cancelled": "Zone upgrade cancelled", diff --git a/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java b/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java new file mode 100644 index 0000000..240bd11 --- /dev/null +++ b/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2026 5thlayer +// SPDX-License-Identifier: MIT + +package io.github._5thlayer.voidworks.displacer; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.List; +import java.util.OptionalInt; + +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.contents.TranslatableContents; +import org.junit.jupiter.api.Test; + +/** The Density line: the Density alone until the motes are known, then with them, one mote said as one. */ +class DensityTooltipTest { + + @Test + void itShowsTheDensityAloneUntilTheMotesAreKnown() { + assertLine("voidworks.density.tooltip", List.of(4), DensityTooltip.line(4, OptionalInt.empty())); + } + + @Test + void itShowsTheMotesOnceKnown() { + assertLine("voidworks.density.tooltip.motes", List.of(4, 64), DensityTooltip.line(4, OptionalInt.of(64))); + } + + @Test + void itSaysOneMoteAsOne() { + assertLine("voidworks.density.tooltip.mote", List.of(1, 1), DensityTooltip.line(1, OptionalInt.of(1))); + } + + private static void assertLine(String key, List args, Component line) { + var contents = (TranslatableContents) line.getContents(); + assertEquals(key, contents.getKey()); + assertEquals(args, List.of(contents.getArgs())); + } +} From 0a2858f4970bce731e6edfcd30eafec7965f8f50 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 19:35:20 +0200 Subject: [PATCH 3/5] refactor: style a density tooltip line once, and say which items show it Co-Authored-By: Claude Opus 5.5 --- docs/spec/void-energy.md | 6 +++--- .../voidworks/displacer/DensityTooltip.java | 16 +++++++++------- .../voidworks/gametest/DensityTooltipTests.java | 6 ++++-- .../voidworks/displacer/DensityTooltipTest.java | 2 +- 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/docs/spec/void-energy.md b/docs/spec/void-energy.md index a2b8f38..5dc8a1b 100644 --- a/docs/spec/void-energy.md +++ b/docs/spec/void-energy.md @@ -157,9 +157,9 @@ it, and it leaves no Voidstone: the renewable and abundant blocks above all (cob deepslate, dirt, sand, gravel, netherrack, blackstone, basalt, end stone, obsidian, snow, ice), and everything made from them, so a generator never feeds a harvest. Density rises steeply (shape: about 4^(density − 1), so 1, 4, 16, 64). Density tags and Families are separate data and need not agree: -amethyst, quartz and glowstone climb the gem and dust Families but stay Density 0, being renewable. A -block item's tooltip shows its Density and the motes one yields in a Displacer; one of Density 0 -shows nothing. +amethyst, quartz and glowstone climb the gem and dust Families but stay Density 0, being renewable. An +item a Density tag names shows its Density in its tooltip, with the motes one yields in a Displacer +once the server's numbers are known; one of Density 0 shows nothing. | Density | Motes | Blocks, raw and refined alike | |---|---|---| diff --git a/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java b/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java index f287b77..54e33a0 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java +++ b/src/main/java/io/github/_5thlayer/voidworks/displacer/DensityTooltip.java @@ -8,6 +8,7 @@ import io.github._5thlayer.voidworks.VoidworksConfig; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import net.neoforged.neoforge.transfer.item.ItemResource; @@ -21,7 +22,7 @@ public final class DensityTooltip { private DensityTooltip() { } - /** Adds the line to every item tooltip built, which only a client builds outside the game tests. */ + /** Adds the line to every item tooltip built: a client's, and the game tests'. */ public static void register() { NeoForge.EVENT_BUS.addListener(DensityTooltip::onItemTooltip); } @@ -30,7 +31,9 @@ private static void onItemTooltip(ItemTooltipEvent event) { int density = Density.of(ItemResource.of(event.getItemStack())); if (density > 0) { // Known on a client only once a server has sent its config. - var motes = VoidworksConfig.loaded() ? OptionalInt.of(VoidworksConfig.motes(density)) : OptionalInt.empty(); + var motes = VoidworksConfig.loaded() + ? OptionalInt.of(VoidworksConfig.motes(density)) + : OptionalInt.empty(); event.getToolTip().add(1, line(density, motes)); } } @@ -40,14 +43,13 @@ private static void onItemTooltip(ItemTooltipEvent event) { * @return the line an item of {@code density}, above 0, shows */ static Component line(int density, OptionalInt motes) { - Component line; + MutableComponent line; if (motes.isEmpty()) { line = Component.translatable("voidworks.density.tooltip", density); - } else if (motes.getAsInt() == 1) { - line = Component.translatable("voidworks.density.tooltip.mote", density, 1); } else { - line = Component.translatable("voidworks.density.tooltip.motes", density, motes.getAsInt()); + String key = motes.getAsInt() == 1 ? "voidworks.density.tooltip.mote" : "voidworks.density.tooltip.motes"; + line = Component.translatable(key, density, motes.getAsInt()); } - return line.copy().withStyle(ChatFormatting.GRAY); + return line.withStyle(ChatFormatting.GRAY); } } diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java index d0849bc..9c05a00 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java @@ -25,8 +25,10 @@ private DensityTooltipTests() { } static void register(VoidworksGameTests.Registrar tests) { - tests.test("density_tooltip_shows_a_diamond_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.DIAMOND_BLOCK, "voidworks.density.tooltip.motes", 4, 64)); - tests.test("density_tooltip_shows_a_copper_blocks_density_and_motes", 1, helper -> showsUnderTheName(helper, Items.COPPER_BLOCK, "voidworks.density.tooltip.mote", 1, 1)); + tests.test("density_tooltip_shows_a_diamond_blocks_density_and_motes", 1, + helper -> showsUnderTheName(helper, Items.DIAMOND_BLOCK, "voidworks.density.tooltip.motes", 4, 64)); + tests.test("density_tooltip_shows_a_copper_blocks_density_and_motes", 1, + helper -> showsUnderTheName(helper, Items.COPPER_BLOCK, "voidworks.density.tooltip.mote", 1, 1)); tests.test("density_tooltip_shows_nothing_for_cobblestone", 1, DensityTooltipTests::showsNothingForDensityZero); } diff --git a/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java b/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java index 240bd11..6d9e23f 100644 --- a/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java +++ b/src/test/java/io/github/_5thlayer/voidworks/displacer/DensityTooltipTest.java @@ -12,7 +12,7 @@ import net.minecraft.network.chat.contents.TranslatableContents; import org.junit.jupiter.api.Test; -/** The Density line: the Density alone until the motes are known, then with them, one mote said as one. */ +/** The Density line: the Density alone until the motes are known, then with them, one said as one. */ class DensityTooltipTest { @Test From 3fb329dbad8d522b67f644d9325d6ae699a9395c Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 19:38:42 +0200 Subject: [PATCH 4/5] docs: name density items, not fed blocks, in the tooltip's javadocs Co-Authored-By: Claude Opus 5.5 --- src/main/java/io/github/_5thlayer/voidworks/Voidworks.java | 2 +- .../_5thlayer/voidworks/gametest/DensityTooltipTests.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java b/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java index 37f801a..0768779 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java +++ b/src/main/java/io/github/_5thlayer/voidworks/Voidworks.java @@ -31,7 +31,7 @@ /** * The Module's entry point. It registers the Void Pressure data map (and checks the defaults it * ships), Voidstone and the Void Displacers with their displacement table and server config, the - * Density line in a fed block's tooltip, the Dormant machines' cost map, conduction through + * Density line in a Density item's tooltip, the Dormant machines' cost map, conduction through * Voidstone networks, the Families, the Unmaking Chamber's breakdown map, the Void Siphon, the * dragon eggs, the Dragonling they hatch and the Void Dragon it grows into, which carries motes * between Void Wells, the {@code /voidworks} commands and the game tests, which exist only when diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java index 9c05a00..2eca1dc 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java @@ -15,7 +15,7 @@ import net.minecraft.world.level.GameType; /** - * A fed block's Density in its tooltip, built on a real server with the server's config: the line + * A Density item's tooltip, built on a real server with the server's config: the line * under a Density item's name, with the motes a Displacer yields from it, and no line for a block of * Density 0. */ From 98f62dc5cf3a41af2541f39c61f2fe0fffcb6ba3 Mon Sep 17 00:00:00 2001 From: Andrea D'Amico Date: Fri, 16 Oct 2026 19:40:46 +0200 Subject: [PATCH 5/5] docs: refill the density tooltip game tests' javadoc Co-Authored-By: Claude Opus 5.5 --- .../_5thlayer/voidworks/gametest/DensityTooltipTests.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java index 2eca1dc..fa2a837 100644 --- a/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java +++ b/src/main/java/io/github/_5thlayer/voidworks/gametest/DensityTooltipTests.java @@ -15,9 +15,8 @@ import net.minecraft.world.level.GameType; /** - * A Density item's tooltip, built on a real server with the server's config: the line - * under a Density item's name, with the motes a Displacer yields from it, and no line for a block of - * Density 0. + * A Density item's tooltip, built on a real server with the server's config: the line under its + * name, with the motes a Displacer yields from it, and no line for a block of Density 0. */ final class DensityTooltipTests {