From 16951f2d4268ae8f0c0692f0517bcdbb69f779f4 Mon Sep 17 00:00:00 2001 From: CoderJoe Date: Thu, 26 Mar 2026 23:42:54 -0500 Subject: [PATCH 1/4] Add round-robin distribution to power and fluid splitters Splitters previously always iterated output faces in a fixed order, causing resources to always favor the same direction. Both PowerSplitter and FluidSplitter now track a nextOutputIndex that advances past the last successful push, cycling through output faces evenly over time. --- .../atlas/fluid/block/FluidSplitter.kt | 6 ++- .../atlas/power/block/PowerSplitter.kt | 10 ++++- .../coderjoe/atlas/fluid/FluidSplitterTest.kt | 42 +++++++++++++++++ .../coderjoe/atlas/power/PowerSplitterTest.kt | 45 +++++++++++++++++++ 4 files changed, 101 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidSplitter.kt b/src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidSplitter.kt index ce9134f..05e2fe2 100644 --- a/src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidSplitter.kt +++ b/src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidSplitter.kt @@ -26,6 +26,7 @@ class FluidSplitter(location: Location, override val facing: BlockFace) : FluidB } override val baseBlockId: String = BLOCK_ID + private var nextOutputIndex: Int = 0 override fun getVisualStateBlockId(): String = BLOCK_ID @@ -47,13 +48,16 @@ class FluidSplitter(location: Location, override val facing: BlockFace) : FluidB if (hasFluid()) { val outputFaces = ADJACENT_FACES.filter { it != facing.oppositeFace } + val faceCount = outputFaces.size - for (face in outputFaces) { + for (i in outputFaces.indices) { if (!hasFluid()) break + val face = outputFaces[(nextOutputIndex + i) % faceCount] val target = registry.getAdjacentFluidBlock(location, face) ?: continue if (!target.hasFluid()) { val fluid = removeFluid() if (target.storeFluid(fluid)) { + nextOutputIndex = (nextOutputIndex + i + 1) % faceCount plugin.logger.atlasInfo( "FluidSplitter at ${location.coordinates} " + "pushed ${fluid.name} to ${target::class.simpleName} at ${face.name}", diff --git a/src/main/kotlin/com/coderjoe/atlas/power/block/PowerSplitter.kt b/src/main/kotlin/com/coderjoe/atlas/power/block/PowerSplitter.kt index 2063391..2169db9 100644 --- a/src/main/kotlin/com/coderjoe/atlas/power/block/PowerSplitter.kt +++ b/src/main/kotlin/com/coderjoe/atlas/power/block/PowerSplitter.kt @@ -26,6 +26,7 @@ class PowerSplitter(location: Location, override val facing: BlockFace) : PowerB override val baseBlockId: String = BLOCK_ID override val updateIntervalTicks: Long = 20L + private var nextOutputIndex: Int = 0 override fun getVisualStateBlockId(): String = BLOCK_ID @@ -48,14 +49,18 @@ class PowerSplitter(location: Location, override val facing: BlockFace) : PowerB if (hasPower()) { val outputFaces = ADJACENT_FACES.filter { it != facing.oppositeFace } + val faceCount = outputFaces.size + var lastPushOffset = -1 - for (face in outputFaces) { + for (i in outputFaces.indices) { if (!hasPower()) break + val face = outputFaces[(nextOutputIndex + i) % faceCount] val target = registry.getAdjacentPowerBlock(location, face) ?: continue if (target.canAcceptPower()) { val pushed = removePower(1) if (pushed > 0) { target.addPower(pushed) + lastPushOffset = i plugin.logger.atlasInfo( "PowerSplitter at ${location.coordinates} " + "pushed $pushed power to ${target::class.simpleName} at ${face.name}", @@ -63,6 +68,9 @@ class PowerSplitter(location: Location, override val facing: BlockFace) : PowerB } } } + if (lastPushOffset >= 0) { + nextOutputIndex = (nextOutputIndex + lastPushOffset + 1) % faceCount + } } updatePoweredState() diff --git a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidSplitterTest.kt b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidSplitterTest.kt index 5b4f2d0..fb2e643 100644 --- a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidSplitterTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidSplitterTest.kt @@ -172,4 +172,46 @@ class FluidSplitterTest { assertEquals("atlas:fluid_splitter", desc.baseBlockId) assertEquals("Fluid Splitter", desc.displayName) } + + @Test + fun `distributes fluid round-robin across multiple updates`() { + // Splitter facing NORTH, input from SOUTH + val splitterLoc = TestHelper.createLocation(0.0, 64.0, 0.0) + val splitter = FluidSplitter(splitterLoc, BlockFace.NORTH) + TestHelper.addToRegistry(registry, splitter, "atlas:fluid_splitter") + + // Two output pipes: east and west (both empty) + val eastLoc = TestHelper.createLocation(1.0, 64.0, 0.0) + val eastPipe = FluidPipe(eastLoc, BlockFace.EAST) + TestHelper.addToRegistry(registry, eastPipe, "atlas:fluid_pipe") + + val westLoc = TestHelper.createLocation(-1.0, 64.0, 0.0) + val westPipe = FluidPipe(westLoc, BlockFace.WEST) + TestHelper.addToRegistry(registry, westPipe, "atlas:fluid_pipe") + + // First update: give splitter fluid, push to one output + splitter.storeFluid(FluidType.WATER) + splitter.callFluidUpdate() + + val firstEast = eastPipe.hasFluid() + val firstWest = westPipe.hasFluid() + assertTrue(firstEast || firstWest, "fluid should go somewhere") + assertFalse(firstEast && firstWest, "only one should receive") + + // Drain the pipes and do it again + eastPipe.removeFluid() + westPipe.removeFluid() + splitter.storeFluid(FluidType.WATER) + splitter.callFluidUpdate() + + val secondEast = eastPipe.hasFluid() + val secondWest = westPipe.hasFluid() + assertTrue(secondEast || secondWest, "fluid should go somewhere") + + // The two rounds should have gone to different targets + assertTrue( + firstEast != secondEast, + "round-robin should alternate: firstEast=$firstEast, secondEast=$secondEast", + ) + } } diff --git a/src/test/kotlin/com/coderjoe/atlas/power/PowerSplitterTest.kt b/src/test/kotlin/com/coderjoe/atlas/power/PowerSplitterTest.kt index cc19d5f..21367c4 100644 --- a/src/test/kotlin/com/coderjoe/atlas/power/PowerSplitterTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/power/PowerSplitterTest.kt @@ -208,4 +208,49 @@ class PowerSplitterTest { splitter.callPowerUpdate() } } + + @Test + fun `distributes power round-robin across multiple updates`() { + val registry = PowerBlockRegistry(TestHelper.mockPlugin) + + // Splitter facing NORTH, input from SOUTH + val splitterLoc = TestHelper.createLocation(0.0, 64.0, 0.0) + val splitter = PowerSplitter(splitterLoc, BlockFace.NORTH) + TestHelper.addToRegistry(registry, splitter, "atlas:power_splitter") + + // Two output batteries: east and west (both can accept power) + val eastLoc = TestHelper.createLocation(1.0, 64.0, 0.0) + val eastBattery = SmallBattery(eastLoc, BlockFace.WEST) + TestHelper.addToRegistry(registry, eastBattery, "atlas:small_battery") + + val westLoc = TestHelper.createLocation(-1.0, 64.0, 0.0) + val westBattery = SmallBattery(westLoc, BlockFace.EAST) + TestHelper.addToRegistry(registry, westBattery, "atlas:small_battery") + + // Give splitter exactly 1 power and update — only one battery should get it + splitter.currentPower = 1 + splitter.callPowerUpdate() + + val firstEast = eastBattery.currentPower + val firstWest = westBattery.currentPower + assertEquals(1, firstEast + firstWest, "exactly 1 power distributed") + + // Reset and do it again — the OTHER battery should get power this time + splitter.currentPower = 1 + eastBattery.currentPower = 0 + westBattery.currentPower = 0 + splitter.callPowerUpdate() + + val secondEast = eastBattery.currentPower + val secondWest = westBattery.currentPower + assertEquals(1, secondEast + secondWest, "exactly 1 power distributed") + + // The two rounds should have gone to different targets + val firstWentEast = firstEast == 1 + val secondWentEast = secondEast == 1 + assertTrue( + firstWentEast != secondWentEast, + "round-robin should alternate: first=$firstWentEast, second=$secondWentEast", + ) + } } From 2d69b0c74976ec9543afd848bfc439c4072805dd Mon Sep 17 00:00:00 2001 From: CoderJoe Date: Thu, 26 Mar 2026 23:43:02 -0500 Subject: [PATCH 2/4] Remove excessive SmallSolarPanel nighttime logging The panel logged "is not generating power because it is not daytime" every 10 seconds per panel during night, creating significant log noise with no diagnostic value. --- .../kotlin/com/coderjoe/atlas/power/block/SmallSolarPanel.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main/kotlin/com/coderjoe/atlas/power/block/SmallSolarPanel.kt b/src/main/kotlin/com/coderjoe/atlas/power/block/SmallSolarPanel.kt index ddb3c5e..6b42806 100644 --- a/src/main/kotlin/com/coderjoe/atlas/power/block/SmallSolarPanel.kt +++ b/src/main/kotlin/com/coderjoe/atlas/power/block/SmallSolarPanel.kt @@ -46,11 +46,6 @@ class SmallSolarPanel(location: Location) : PowerBlock(location, maxStorage = 4) "generated $generated power (now $currentPower/$maxStorage)", ) } - } else { - plugin.logger.atlasInfo( - "SmallSolarPanel at ${location.coordinates} " + - "is not generating power because it is not daytime.", - ) } } } From f886abffbc19567bbe2a385604b9049932ad347c Mon Sep 17 00:00:00 2001 From: CoderJoe Date: Thu, 26 Mar 2026 23:43:12 -0500 Subject: [PATCH 3/4] Remove unused PowerBlockData and FluidBlockData classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These data classes were never used in production code — BlockPersistence handles all serialization directly. Also removes redundant locationKey companion delegation from all three registry subclasses. --- .../coderjoe/atlas/fluid/FluidBlockData.kt | 67 --------- .../atlas/fluid/FluidBlockRegistry.kt | 2 - .../coderjoe/atlas/power/PowerBlockData.kt | 54 -------- .../atlas/power/PowerBlockRegistry.kt | 2 - .../atlas/transport/TransportBlockRegistry.kt | 2 - .../kotlin/com/coderjoe/atlas/TestHelper.kt | 6 +- .../atlas/fluid/FluidBlockDataTest.kt | 117 ---------------- .../atlas/fluid/FluidBlockListenerTest.kt | 5 +- .../atlas/fluid/FluidBlockRegistryTest.kt | 3 +- .../atlas/fluid/FluidContainerTest.kt | 15 -- .../atlas/power/PowerBlockDataTest.kt | 128 ------------------ .../atlas/power/PowerBlockListenerTest.kt | 5 +- .../atlas/power/PowerBlockRegistryTest.kt | 3 +- 13 files changed, 13 insertions(+), 396 deletions(-) delete mode 100644 src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockData.kt delete mode 100644 src/main/kotlin/com/coderjoe/atlas/power/PowerBlockData.kt delete mode 100644 src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockDataTest.kt delete mode 100644 src/test/kotlin/com/coderjoe/atlas/power/PowerBlockDataTest.kt diff --git a/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockData.kt b/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockData.kt deleted file mode 100644 index d83e58d..0000000 --- a/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockData.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.coderjoe.atlas.fluid - -import com.coderjoe.atlas.fluid.block.FluidContainer -import org.bukkit.Location -import org.bukkit.block.BlockFace -import org.bukkit.plugin.java.JavaPlugin - -data class FluidBlockData( - val blockId: String, - val world: String, - val x: Int, - val y: Int, - val z: Int, - val fluidType: String, - val facing: String? = null, - val storedAmount: Int? = null, -) { - companion object { - fun fromFluidBlock( - fluidBlock: FluidBlock, - blockId: String, - ): FluidBlockData { - val loc = fluidBlock.location - val facing = fluidBlock.facing.let { if (it == BlockFace.SELF) null else it.name } - val storedAmount = - when (fluidBlock) { - is FluidContainer -> fluidBlock.storedAmount - else -> null - } - return FluidBlockData( - blockId = blockId, - world = loc.world?.name ?: "world", - x = loc.blockX, - y = loc.blockY, - z = loc.blockZ, - fluidType = fluidBlock.storedFluid.name, - facing = facing, - storedAmount = storedAmount, - ) - } - } - - fun toLocation(plugin: JavaPlugin): Location? { - val world = plugin.server.getWorld(this.world) ?: return null - return Location(world, x.toDouble(), y.toDouble(), z.toDouble()) - } - - fun toBlockFace(): BlockFace { - return if (facing != null) { - try { - BlockFace.valueOf(facing) - } catch (_: Exception) { - BlockFace.SELF - } - } else { - BlockFace.SELF - } - } - - fun toFluidType(): FluidType { - return try { - FluidType.valueOf(fluidType) - } catch (_: Exception) { - FluidType.NONE - } - } -} diff --git a/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistry.kt b/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistry.kt index 24026d4..1354a47 100644 --- a/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistry.kt +++ b/src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistry.kt @@ -9,8 +9,6 @@ class FluidBlockRegistry(plugin: JavaPlugin) : BlockRegistry(plugin) companion object { var instance: FluidBlockRegistry? = null private set - - fun locationKey(location: Location): String = BlockRegistry.locationKey(location) } init { diff --git a/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockData.kt b/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockData.kt deleted file mode 100644 index fd9c8eb..0000000 --- a/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockData.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.coderjoe.atlas.power - -import com.coderjoe.atlas.utility.block.SmallDrill -import org.bukkit.Location -import org.bukkit.block.BlockFace - -data class PowerBlockData( - val blockId: String, - val world: String, - val x: Int, - val y: Int, - val z: Int, - val currentPower: Int, - val facing: String? = null, - val enabled: Boolean? = null, -) { - companion object { - fun fromPowerBlock( - powerBlock: PowerBlock, - blockId: String, - ): PowerBlockData { - val loc = powerBlock.location - val facing = powerBlock.facing.let { if (it == BlockFace.SELF) null else it.name } - val enabled = if (powerBlock is SmallDrill) powerBlock.enabled else null - return PowerBlockData( - blockId = blockId, - world = loc.world?.name ?: "world", - x = loc.blockX, - y = loc.blockY, - z = loc.blockZ, - currentPower = powerBlock.currentPower, - facing = facing, - enabled = enabled, - ) - } - } - - fun toLocation(plugin: org.bukkit.plugin.java.JavaPlugin): Location? { - val world = plugin.server.getWorld(this.world) ?: return null - return Location(world, x.toDouble(), y.toDouble(), z.toDouble()) - } - - fun toBlockFace(): BlockFace { - return if (facing != null) { - try { - BlockFace.valueOf(facing) - } catch (_: Exception) { - BlockFace.SELF - } - } else { - BlockFace.SELF - } - } -} diff --git a/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockRegistry.kt b/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockRegistry.kt index 683977b..9f52378 100644 --- a/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockRegistry.kt +++ b/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockRegistry.kt @@ -9,8 +9,6 @@ class PowerBlockRegistry(plugin: JavaPlugin) : BlockRegistry(plugin) companion object { var instance: PowerBlockRegistry? = null private set - - fun locationKey(location: Location): String = BlockRegistry.locationKey(location) } init { diff --git a/src/main/kotlin/com/coderjoe/atlas/transport/TransportBlockRegistry.kt b/src/main/kotlin/com/coderjoe/atlas/transport/TransportBlockRegistry.kt index 5c93db1..b826782 100644 --- a/src/main/kotlin/com/coderjoe/atlas/transport/TransportBlockRegistry.kt +++ b/src/main/kotlin/com/coderjoe/atlas/transport/TransportBlockRegistry.kt @@ -9,8 +9,6 @@ class TransportBlockRegistry(plugin: JavaPlugin) : BlockRegistry companion object { var instance: TransportBlockRegistry? = null private set - - fun locationKey(location: Location): String = BlockRegistry.locationKey(location) } init { diff --git a/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt b/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt index 69accb4..4a9ac08 100644 --- a/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt +++ b/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt @@ -129,7 +129,7 @@ object TestHelper { @Suppress("UNCHECKED_CAST") val blockIds = blockIdsField.get(registry) as java.util.concurrent.ConcurrentHashMap - val key = PowerBlockRegistry.locationKey(block.location) + val key = BlockRegistry.locationKey(block.location) blocks[key] = block blockIds[key] = blockId } @@ -149,7 +149,7 @@ object TestHelper { @Suppress("UNCHECKED_CAST") val blockIds = blockIdsField.get(registry) as java.util.concurrent.ConcurrentHashMap - val key = TransportBlockRegistry.locationKey(block.location) + val key = BlockRegistry.locationKey(block.location) blocks[key] = block blockIds[key] = blockId } @@ -169,7 +169,7 @@ object TestHelper { @Suppress("UNCHECKED_CAST") val blockIds = blockIdsField.get(registry) as java.util.concurrent.ConcurrentHashMap - val key = FluidBlockRegistry.locationKey(block.location) + val key = BlockRegistry.locationKey(block.location) blocks[key] = block blockIds[key] = blockId } diff --git a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockDataTest.kt b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockDataTest.kt deleted file mode 100644 index ccd088a..0000000 --- a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockDataTest.kt +++ /dev/null @@ -1,117 +0,0 @@ -package com.coderjoe.atlas.fluid - -import com.coderjoe.atlas.TestHelper -import com.coderjoe.atlas.fluid.block.FluidPipe -import com.coderjoe.atlas.fluid.block.FluidPump -import org.bukkit.block.BlockFace -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotNull -import org.junit.jupiter.api.Assertions.assertNull -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -class FluidBlockDataTest { - @BeforeEach - fun setup() { - TestHelper.setup() - } - - @AfterEach - fun teardown() { - TestHelper.teardown() - } - - @Test - fun `fromFluidBlock for FluidPump`() { - val pump = FluidPump(TestHelper.createLocation(1.0, 2.0, 3.0)) - pump.storeFluid(FluidType.WATER) - val data = FluidBlockData.fromFluidBlock(pump, "atlas:fluid_pump") - - assertEquals("atlas:fluid_pump", data.blockId) - assertEquals("world", data.world) - assertEquals(1, data.x) - assertEquals(2, data.y) - assertEquals(3, data.z) - assertEquals("WATER", data.fluidType) - assertNull(data.facing) - } - - @Test - fun `fromFluidBlock for FluidPipe captures facing`() { - val pipe = FluidPipe(TestHelper.createLocation(), BlockFace.EAST) - val data = FluidBlockData.fromFluidBlock(pipe, "atlas:fluid_pipe") - assertEquals("EAST", data.facing) - } - - @Test - fun `toBlockFace with valid string`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "NONE", facing = "WEST") - assertEquals(BlockFace.WEST, data.toBlockFace()) - } - - @Test - fun `toBlockFace with null returns SELF`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "NONE", facing = null) - assertEquals(BlockFace.SELF, data.toBlockFace()) - } - - @Test - fun `toBlockFace with invalid returns SELF`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "NONE", facing = "INVALID") - assertEquals(BlockFace.SELF, data.toBlockFace()) - } - - @Test - fun `toFluidType WATER`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "WATER") - assertEquals(FluidType.WATER, data.toFluidType()) - } - - @Test - fun `toFluidType LAVA`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "LAVA") - assertEquals(FluidType.LAVA, data.toFluidType()) - } - - @Test - fun `toFluidType NONE`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "NONE") - assertEquals(FluidType.NONE, data.toFluidType()) - } - - @Test - fun `toFluidType invalid defaults to NONE`() { - val data = FluidBlockData("id", "world", 0, 0, 0, "INVALID") - assertEquals(FluidType.NONE, data.toFluidType()) - } - - @Test - fun `toLocation with valid world`() { - val data = FluidBlockData("id", "world", 5, 64, 10, "NONE") - val loc = data.toLocation(TestHelper.mockPlugin) - assertNotNull(loc) - assertEquals(5.0, loc!!.x) - assertEquals(64.0, loc.y) - assertEquals(10.0, loc.z) - } - - @Test - fun `toLocation with invalid world returns null`() { - val data = FluidBlockData("id", "nonexistent", 0, 0, 0, "NONE") - assertNull(data.toLocation(TestHelper.mockPlugin)) - } - - @Test - fun `round-trip FluidPipe preserves all fields`() { - val pipe = FluidPipe(TestHelper.createLocation(1.0, 2.0, 3.0), BlockFace.NORTH) - pipe.storeFluid(FluidType.LAVA) - val data = FluidBlockData.fromFluidBlock(pipe, "atlas:fluid_pipe") - - assertEquals("atlas:fluid_pipe", data.blockId) - assertEquals("NORTH", data.facing) - assertEquals("LAVA", data.fluidType) - assertEquals(BlockFace.NORTH, data.toBlockFace()) - assertEquals(FluidType.LAVA, data.toFluidType()) - } -} diff --git a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockListenerTest.kt b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockListenerTest.kt index a14c446..a28801c 100644 --- a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockListenerTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockListenerTest.kt @@ -2,6 +2,7 @@ package com.coderjoe.atlas.fluid import com.coderjoe.atlas.TestHelper import com.coderjoe.atlas.core.AtlasBlockListener +import com.coderjoe.atlas.core.BlockRegistry import com.coderjoe.atlas.core.BlockSystem import com.coderjoe.atlas.fluid.block.FluidPump import io.mockk.every @@ -46,7 +47,7 @@ class FluidBlockListenerTest { @Test fun `onBlockPlace skips when in updatingLocations`() { val loc = TestHelper.createLocation() - val key = FluidBlockRegistry.locationKey(loc) + val key = BlockRegistry.locationKey(loc) registry.updatingLocations.add(key) val block = mockk(relaxed = true) @@ -61,7 +62,7 @@ class FluidBlockListenerTest { @Test fun `onBlockBreak skips when in updatingLocations`() { val loc = TestHelper.createLocation() - val key = FluidBlockRegistry.locationKey(loc) + val key = BlockRegistry.locationKey(loc) registry.updatingLocations.add(key) val block = mockk(relaxed = true) diff --git a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistryTest.kt b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistryTest.kt index d2896df..db91ed8 100644 --- a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistryTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidBlockRegistryTest.kt @@ -1,6 +1,7 @@ package com.coderjoe.atlas.fluid import com.coderjoe.atlas.TestHelper +import com.coderjoe.atlas.core.BlockRegistry import com.coderjoe.atlas.fluid.block.FluidPipe import com.coderjoe.atlas.fluid.block.FluidPump import org.bukkit.block.BlockFace @@ -29,7 +30,7 @@ class FluidBlockRegistryTest { @Test fun `locationKey produces correct format`() { val loc = TestHelper.createLocation(5.0, 100.0, -3.0) - assertEquals("world:5,100,-3", FluidBlockRegistry.locationKey(loc)) + assertEquals("world:5,100,-3", BlockRegistry.locationKey(loc)) } @Test diff --git a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt index 20d532c..c12d62c 100644 --- a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt @@ -479,19 +479,4 @@ class FluidContainerTest { assertEquals(FluidContainer.MAX_CAPACITY, container.storedAmount) } - @Test - fun `FluidBlockData captures container facing and storedAmount`() { - val container = - FluidContainer(TestHelper.createLocation(), BlockFace.EAST) - repeat(5) { container.storeFluid(FluidType.WATER) } - - val data = - FluidBlockData.fromFluidBlock( - container, - "atlas:fluid_container", - ) - assertEquals("EAST", data.facing) - assertEquals(5, data.storedAmount) - assertEquals("WATER", data.fluidType) - } } diff --git a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockDataTest.kt b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockDataTest.kt deleted file mode 100644 index 447003e..0000000 --- a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockDataTest.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.coderjoe.atlas.power - -import com.coderjoe.atlas.TestHelper -import com.coderjoe.atlas.power.block.PowerCable -import com.coderjoe.atlas.power.block.SmallBattery -import com.coderjoe.atlas.power.block.SmallSolarPanel -import com.coderjoe.atlas.utility.block.SmallDrill -import org.bukkit.block.BlockFace -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotNull -import org.junit.jupiter.api.Assertions.assertNull -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -class PowerBlockDataTest { - @BeforeEach - fun setup() { - TestHelper.setup() - } - - @AfterEach - fun teardown() { - TestHelper.teardown() - } - - @Test - fun `fromPowerBlock for SmallSolarPanel`() { - val loc = TestHelper.createLocation(10.0, 64.0, 20.0) - val panel = SmallSolarPanel(loc) - panel.currentPower = 1 - val data = PowerBlockData.fromPowerBlock(panel, "atlas:small_solar_panel") - - assertEquals("atlas:small_solar_panel", data.blockId) - assertEquals("world", data.world) - assertEquals(10, data.x) - assertEquals(64, data.y) - assertEquals(20, data.z) - assertEquals(1, data.currentPower) - assertNull(data.facing) - assertNull(data.enabled) - } - - @Test - fun `fromPowerBlock for PowerCable captures facing`() { - val cable = PowerCable(TestHelper.createLocation(), BlockFace.EAST) - val data = PowerBlockData.fromPowerBlock(cable, "atlas:power_cable") - assertEquals("EAST", data.facing) - } - - @Test - fun `fromPowerBlock for SmallDrill captures facing and enabled`() { - val drill = SmallDrill(TestHelper.createLocation(), BlockFace.NORTH) - drill.enabled = false - val data = PowerBlockData.fromPowerBlock(drill, "atlas:small_drill") - assertEquals("NORTH", data.facing) - assertEquals(false, data.enabled) - } - - @Test - fun `fromPowerBlock for SmallBattery captures facing`() { - val battery = SmallBattery(TestHelper.createLocation(), BlockFace.UP) - val data = PowerBlockData.fromPowerBlock(battery, "atlas:small_battery") - assertEquals("UP", data.facing) - } - - @Test - fun `toBlockFace with valid facing string`() { - val data = PowerBlockData("id", "world", 0, 0, 0, 0, facing = "NORTH") - assertEquals(BlockFace.NORTH, data.toBlockFace()) - } - - @Test - fun `toBlockFace with null facing returns SELF`() { - val data = PowerBlockData("id", "world", 0, 0, 0, 0, facing = null) - assertEquals(BlockFace.SELF, data.toBlockFace()) - } - - @Test - fun `toBlockFace with invalid string returns SELF`() { - val data = PowerBlockData("id", "world", 0, 0, 0, 0, facing = "INVALID") - assertEquals(BlockFace.SELF, data.toBlockFace()) - } - - @Test - fun `toLocation with valid world`() { - val data = PowerBlockData("id", "world", 5, 64, 10, 0) - val loc = data.toLocation(TestHelper.mockPlugin) - assertNotNull(loc) - assertEquals(5.0, loc!!.x) - assertEquals(64.0, loc.y) - assertEquals(10.0, loc.z) - } - - @Test - fun `toLocation with invalid world returns null`() { - val data = PowerBlockData("id", "nonexistent_world", 0, 0, 0, 0) - val loc = data.toLocation(TestHelper.mockPlugin) - assertNull(loc) - } - - @Test - fun `round-trip SmallSolarPanel preserves all fields`() { - val loc = TestHelper.createLocation(1.0, 2.0, 3.0) - val panel = SmallSolarPanel(loc) - panel.currentPower = 1 - val data = PowerBlockData.fromPowerBlock(panel, "atlas:small_solar_panel") - - assertEquals("atlas:small_solar_panel", data.blockId) - assertEquals(1, data.x) - assertEquals(2, data.y) - assertEquals(3, data.z) - assertEquals(1, data.currentPower) - } - - @Test - fun `round-trip SmallDrill preserves facing and enabled`() { - val drill = SmallDrill(TestHelper.createLocation(), BlockFace.WEST) - drill.enabled = true - drill.currentPower = 5 - val data = PowerBlockData.fromPowerBlock(drill, "atlas:small_drill") - - assertEquals("WEST", data.facing) - assertEquals(true, data.enabled) - assertEquals(5, data.currentPower) - assertEquals(BlockFace.WEST, data.toBlockFace()) - } -} diff --git a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockListenerTest.kt b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockListenerTest.kt index fa2f530..1ab1088 100644 --- a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockListenerTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockListenerTest.kt @@ -2,6 +2,7 @@ package com.coderjoe.atlas.power import com.coderjoe.atlas.TestHelper import com.coderjoe.atlas.core.AtlasBlockListener +import com.coderjoe.atlas.core.BlockRegistry import com.coderjoe.atlas.core.BlockSystem import com.coderjoe.atlas.power.block.SmallSolarPanel import io.mockk.every @@ -46,7 +47,7 @@ class PowerBlockListenerTest { @Test fun `onBlockPlace skips when location in updatingLocations`() { val loc = TestHelper.createLocation() - val key = PowerBlockRegistry.locationKey(loc) + val key = BlockRegistry.locationKey(loc) registry.updatingLocations.add(key) val block = mockk(relaxed = true) @@ -61,7 +62,7 @@ class PowerBlockListenerTest { @Test fun `onBlockBreak skips when in updatingLocations`() { val loc = TestHelper.createLocation() - val key = PowerBlockRegistry.locationKey(loc) + val key = BlockRegistry.locationKey(loc) registry.updatingLocations.add(key) val block = mockk(relaxed = true) diff --git a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockRegistryTest.kt b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockRegistryTest.kt index d2ba47c..6e33905 100644 --- a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockRegistryTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockRegistryTest.kt @@ -1,6 +1,7 @@ package com.coderjoe.atlas.power import com.coderjoe.atlas.TestHelper +import com.coderjoe.atlas.core.BlockRegistry import com.coderjoe.atlas.power.block.SmallBattery import com.coderjoe.atlas.power.block.SmallSolarPanel import org.bukkit.block.BlockFace @@ -29,7 +30,7 @@ class PowerBlockRegistryTest { @Test fun `locationKey produces correct format`() { val loc = TestHelper.createLocation(10.0, 64.0, -5.0) - val key = PowerBlockRegistry.locationKey(loc) + val key = BlockRegistry.locationKey(loc) assertEquals("world:10,64,-5", key) } From 0fa039c81eae5b9b620f9b2a2b6d532c69d4170c Mon Sep 17 00:00:00 2001 From: CoderJoe Date: Thu, 26 Mar 2026 23:44:58 -0500 Subject: [PATCH 4/4] Remove unnecessary blank line in FluidContainerTest --- src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt index c12d62c..db6b648 100644 --- a/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/fluid/FluidContainerTest.kt @@ -478,5 +478,4 @@ class FluidContainerTest { container.restoreState(FluidType.WATER, 99) assertEquals(FluidContainer.MAX_CAPACITY, container.storedAmount) } - }