diff --git a/src/main/kotlin/com/coderjoe/atlas/Atlas.kt b/src/main/kotlin/com/coderjoe/atlas/Atlas.kt index 44f1d83..50507be 100644 --- a/src/main/kotlin/com/coderjoe/atlas/Atlas.kt +++ b/src/main/kotlin/com/coderjoe/atlas/Atlas.kt @@ -180,7 +180,8 @@ class Atlas : JavaPlugin() { com.coderjoe.atlas.power.block.SmallBattery.descriptor, com.coderjoe.atlas.power.block.PowerCable.descriptor, com.coderjoe.atlas.power.block.LavaGenerator.descriptor, - com.coderjoe.atlas.power.block.AutoSmelter.descriptor + com.coderjoe.atlas.power.block.AutoSmelter.descriptor, + com.coderjoe.atlas.power.block.MultiPowerCable.descriptor ).associateBy { it.baseBlockId } } diff --git a/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockDialog.kt b/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockDialog.kt index bb62079..5459e8b 100644 --- a/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockDialog.kt +++ b/src/main/kotlin/com/coderjoe/atlas/power/PowerBlockDialog.kt @@ -7,6 +7,7 @@ import com.coderjoe.atlas.power.block.LavaGenerator import com.coderjoe.atlas.power.block.PowerCable import com.coderjoe.atlas.power.block.SmallBattery import com.coderjoe.atlas.power.block.SmallDrill +import com.coderjoe.atlas.power.block.MultiPowerCable import com.coderjoe.atlas.power.block.SmallSolarPanel import io.papermc.paper.dialog.Dialog import io.papermc.paper.registry.data.dialog.ActionButton @@ -127,6 +128,7 @@ object PowerBlockDialog { is PowerCable -> "Power Cable (${powerBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})" is LavaGenerator -> "Lava Generator" is AutoSmelter -> "Auto Smelter (${powerBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})" + is MultiPowerCable -> "Multi Power Cable (${powerBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})" else -> "Power Block" } @@ -173,6 +175,8 @@ object PowerBlockDialog { .color(NamedTextColor.GRAY) is AutoSmelter -> Component.text("Machine - smelts items passing through, consumes ${AutoSmelter.POWER_PER_SMELT} power/item") .color(NamedTextColor.GRAY) + is MultiPowerCable -> Component.text("Cable - distributes power to all adjacent faces") + .color(NamedTextColor.GRAY) else -> Component.text("Power block") .color(NamedTextColor.GRAY) } diff --git a/src/main/kotlin/com/coderjoe/atlas/power/block/MultiPowerCable.kt b/src/main/kotlin/com/coderjoe/atlas/power/block/MultiPowerCable.kt new file mode 100644 index 0000000..db4cc5f --- /dev/null +++ b/src/main/kotlin/com/coderjoe/atlas/power/block/MultiPowerCable.kt @@ -0,0 +1,91 @@ +package com.coderjoe.atlas.power.block + +import com.coderjoe.atlas.atlasInfo +import com.coderjoe.atlas.core.BlockDescriptor +import com.coderjoe.atlas.core.PlacementType +import com.coderjoe.atlas.power.PowerBlock +import com.coderjoe.atlas.power.PowerBlockRegistry +import org.bukkit.Location +import org.bukkit.block.BlockFace + +class MultiPowerCable(location: Location, override val facing: BlockFace) : PowerBlock(location, maxStorage = 10) { + + companion object { + const val BLOCK_ID = "multi_power_cable" + + val DIRECTIONAL_IDS = mapOf( + BlockFace.NORTH to "multi_power_cable_north", + BlockFace.SOUTH to "multi_power_cable_south", + BlockFace.EAST to "multi_power_cable_east", + BlockFace.WEST to "multi_power_cable_west", + BlockFace.UP to "multi_power_cable_up", + BlockFace.DOWN to "multi_power_cable_down" + ) + + val POWERED_IDS = mapOf( + BlockFace.NORTH to "multi_power_cable_north_powered", + BlockFace.SOUTH to "multi_power_cable_south_powered", + BlockFace.EAST to "multi_power_cable_east_powered", + BlockFace.WEST to "multi_power_cable_west_powered", + BlockFace.UP to "multi_power_cable_up_powered", + BlockFace.DOWN to "multi_power_cable_down_powered" + ) + + val ID_TO_FACING = (DIRECTIONAL_IDS.entries.associate { (face, id) -> id to face } + + POWERED_IDS.entries.associate { (face, id) -> id to face }) + + fun facingFromBlockId(blockId: String): BlockFace? = ID_TO_FACING[blockId] + + val descriptor = BlockDescriptor( + baseBlockId = BLOCK_ID, + displayName = "Multi Power Cable", + description = "Cable - distributes power to all adjacent faces", + placementType = PlacementType.DIRECTIONAL, + directionalVariants = DIRECTIONAL_IDS, + allRegistrableIds = DIRECTIONAL_IDS.values.toList() + POWERED_IDS.values.toList(), + constructor = { loc, facing -> MultiPowerCable(loc, facing) } + ) + } + + override val baseBlockId: String = BLOCK_ID + + override val updateIntervalTicks: Long = 20L // 1 second + + override fun getVisualStateBlockId(): String = + if (currentPower > 0) POWERED_IDS[facing]!! + else DIRECTIONAL_IDS[facing]!! + + override fun powerUpdate() { + val registry = PowerBlockRegistry.instance ?: return + + // Pull power from behind (opposite of facing direction) + val source = registry.getAdjacentPowerBlock(location, facing.oppositeFace) + + if (source != null && canAcceptPower() && source.hasPower()) { + val remaining = maxStorage - currentPower + val pulled = source.removePower(minOf(remaining, source.currentPower)) + if (pulled > 0) { + addPower(pulled) + plugin.logger.atlasInfo("MultiPowerCable at ${location.blockX},${location.blockY},${location.blockZ} pulled $pulled power (now $currentPower/$maxStorage)") + } + } + + // Push 1 power to each adjacent power block on the other 5 faces + if (!hasPower()) return + + val outputFaces = listOf(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN) + .filter { it != facing.oppositeFace } + + for (face in outputFaces) { + if (!hasPower()) break + val target = registry.getAdjacentPowerBlock(location, face) ?: continue + if (target.canAcceptPower()) { + val pushed = removePower(1) + if (pushed > 0) { + target.addPower(pushed) + plugin.logger.atlasInfo("MultiPowerCable at ${location.blockX},${location.blockY},${location.blockZ} pushed $pushed power to ${target::class.simpleName} at ${face.name}") + } + } + } + } +} diff --git a/src/main/resources/nexo/items/atlas_blocks.yml b/src/main/resources/nexo/items/atlas_blocks.yml index 92e7257..78cd2bf 100644 --- a/src/main/resources/nexo/items/atlas_blocks.yml +++ b/src/main/resources/nexo/items/atlas_blocks.yml @@ -3130,3 +3130,388 @@ auto_smelter_west_on: loots: - nexo_item: auto_smelter probability: 1.0 + +multi_power_cable: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube_all + textures: + all: atlas:block/multi_power_cable_side + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 154 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_north: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_front + south: atlas:block/multi_power_cable_back + east: atlas:block/multi_power_cable_side + west: atlas:block/multi_power_cable_side + up: atlas:block/multi_power_cable_cap + down: atlas:block/multi_power_cable_cap + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 155 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_south: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_back + south: atlas:block/multi_power_cable_front + east: atlas:block/multi_power_cable_side + west: atlas:block/multi_power_cable_side + up: atlas:block/multi_power_cable_cap + down: atlas:block/multi_power_cable_cap + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 156 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_east: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side + south: atlas:block/multi_power_cable_side + east: atlas:block/multi_power_cable_front + west: atlas:block/multi_power_cable_back + up: atlas:block/multi_power_cable_cap + down: atlas:block/multi_power_cable_cap + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 157 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_west: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side + south: atlas:block/multi_power_cable_side + east: atlas:block/multi_power_cable_back + west: atlas:block/multi_power_cable_front + up: atlas:block/multi_power_cable_cap + down: atlas:block/multi_power_cable_cap + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 158 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_up: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side + south: atlas:block/multi_power_cable_side + east: atlas:block/multi_power_cable_side + west: atlas:block/multi_power_cable_side + up: atlas:block/multi_power_cable_front + down: atlas:block/multi_power_cable_back + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 159 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_down: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side + south: atlas:block/multi_power_cable_side + east: atlas:block/multi_power_cable_side + west: atlas:block/multi_power_cable_side + up: atlas:block/multi_power_cable_back + down: atlas:block/multi_power_cable_front + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 160 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_north_powered: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_front_powered + south: atlas:block/multi_power_cable_back_powered + east: atlas:block/multi_power_cable_side_powered + west: atlas:block/multi_power_cable_side_powered + up: atlas:block/multi_power_cable_cap_powered + down: atlas:block/multi_power_cable_cap_powered + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 161 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_south_powered: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_back_powered + south: atlas:block/multi_power_cable_front_powered + east: atlas:block/multi_power_cable_side_powered + west: atlas:block/multi_power_cable_side_powered + up: atlas:block/multi_power_cable_cap_powered + down: atlas:block/multi_power_cable_cap_powered + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 162 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_east_powered: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side_powered + south: atlas:block/multi_power_cable_side_powered + east: atlas:block/multi_power_cable_front_powered + west: atlas:block/multi_power_cable_back_powered + up: atlas:block/multi_power_cable_cap_powered + down: atlas:block/multi_power_cable_cap_powered + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 163 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_west_powered: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side_powered + south: atlas:block/multi_power_cable_side_powered + east: atlas:block/multi_power_cable_back_powered + west: atlas:block/multi_power_cable_front_powered + up: atlas:block/multi_power_cable_cap_powered + down: atlas:block/multi_power_cable_cap_powered + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 164 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_up_powered: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side_powered + south: atlas:block/multi_power_cable_side_powered + east: atlas:block/multi_power_cable_side_powered + west: atlas:block/multi_power_cable_side_powered + up: atlas:block/multi_power_cable_front_powered + down: atlas:block/multi_power_cable_back_powered + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 165 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.hit + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 + +multi_power_cable_down_powered: + itemname: "Multi Power Cable" + material: paper + Pack: + generate_model: true + parent_model: block/cube + textures: + north: atlas:block/multi_power_cable_side_powered + south: atlas:block/multi_power_cable_side_powered + east: atlas:block/multi_power_cable_side_powered + west: atlas:block/multi_power_cable_side_powered + up: atlas:block/multi_power_cable_back_powered + down: atlas:block/multi_power_cable_front_powered + Mechanics: + custom_block: + type: NOTEBLOCK + custom_variation: 166 + hardness: 2 + block_sounds: + break_sound: block.metal.break + place_sound: block.metal.place + hit_sound: block.metal.hit + step_sound: block.metal.step + fall_sound: block.metal.fall + drop: + silktouch: false + loots: + - nexo_item: multi_power_cable + probability: 1.0 diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_back.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_back.png new file mode 100644 index 0000000..8ee9965 Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_back.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_back_powered.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_back_powered.png new file mode 100644 index 0000000..2a455b8 Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_back_powered.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_cap.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_cap.png new file mode 100644 index 0000000..6036b66 Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_cap.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_cap_powered.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_cap_powered.png new file mode 100644 index 0000000..006e3d8 Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_cap_powered.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_front.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_front.png new file mode 100644 index 0000000..cdfc96f Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_front.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_front_powered.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_front_powered.png new file mode 100644 index 0000000..736fdac Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_front_powered.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_side.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_side.png new file mode 100644 index 0000000..006e3d8 Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_side.png differ diff --git a/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_side_powered.png b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_side_powered.png new file mode 100644 index 0000000..cdfc96f Binary files /dev/null and b/src/main/resources/nexo/pack/assets/atlas/textures/block/multi_power_cable_side_powered.png differ diff --git a/src/main/resources/nexo/recipes/shapeless/atlas_recipes.yml b/src/main/resources/nexo/recipes/shapeless/atlas_recipes.yml index 2123a03..c4c2763 100644 --- a/src/main/resources/nexo/recipes/shapeless/atlas_recipes.yml +++ b/src/main/resources/nexo/recipes/shapeless/atlas_recipes.yml @@ -6,13 +6,22 @@ small_solar_panel_recipe: amount: 1 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 - minecraft_type: LAPIS_LAZULI + minecraft_type: IRON_INGOT C: - amount: 3 + minecraft_type: IRON_INGOT + D: + minecraft_type: LAPIS_LAZULI + E: + minecraft_type: LAPIS_LAZULI + F: + minecraft_type: LAPIS_LAZULI + G: + minecraft_type: REDSTONE + H: + minecraft_type: REDSTONE + I: minecraft_type: REDSTONE power_cable_recipe: @@ -21,7 +30,6 @@ power_cable_recipe: amount: 1 ingredients: A: - amount: 1 minecraft_type: COPPER_INGOT small_drill_recipe: @@ -30,13 +38,18 @@ small_drill_recipe: amount: 1 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 - minecraft_type: REDSTONE + minecraft_type: IRON_INGOT C: - amount: 1 + minecraft_type: IRON_INGOT + D: + minecraft_type: REDSTONE + E: + minecraft_type: REDSTONE + F: + minecraft_type: REDSTONE + G: minecraft_type: DIAMOND small_battery_recipe: @@ -45,13 +58,18 @@ small_battery_recipe: amount: 1 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 - minecraft_type: REDSTONE + minecraft_type: IRON_INGOT C: - amount: 1 + minecraft_type: IRON_INGOT + D: + minecraft_type: REDSTONE + E: + minecraft_type: REDSTONE + F: + minecraft_type: REDSTONE + G: minecraft_type: COPPER_INGOT fluid_pump_recipe: @@ -60,13 +78,18 @@ fluid_pump_recipe: amount: 1 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 - minecraft_type: REDSTONE + minecraft_type: IRON_INGOT C: - amount: 1 + minecraft_type: IRON_INGOT + D: + minecraft_type: REDSTONE + E: + minecraft_type: REDSTONE + F: + minecraft_type: REDSTONE + G: minecraft_type: BUCKET fluid_pipe_recipe: @@ -75,7 +98,6 @@ fluid_pipe_recipe: amount: 1 ingredients: A: - amount: 1 minecraft_type: IRON_INGOT fluid_container_recipe: @@ -84,13 +106,22 @@ fluid_container_recipe: amount: 1 ingredients: A: - amount: 4 minecraft_type: IRON_INGOT B: - amount: 4 - minecraft_type: GLASS + minecraft_type: IRON_INGOT C: - amount: 1 + minecraft_type: IRON_INGOT + D: + minecraft_type: IRON_INGOT + E: + minecraft_type: GLASS + F: + minecraft_type: GLASS + G: + minecraft_type: GLASS + H: + minecraft_type: GLASS + I: minecraft_type: BUCKET lava_generator_recipe: @@ -99,13 +130,18 @@ lava_generator_recipe: amount: 1 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 - minecraft_type: REDSTONE + minecraft_type: IRON_INGOT C: - amount: 1 + minecraft_type: IRON_INGOT + D: + minecraft_type: REDSTONE + E: + minecraft_type: REDSTONE + F: + minecraft_type: REDSTONE + G: minecraft_type: MAGMA_BLOCK conveyor_belt_recipe: @@ -114,23 +150,48 @@ conveyor_belt_recipe: amount: 4 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 + minecraft_type: IRON_INGOT + C: + minecraft_type: IRON_INGOT + D: + minecraft_type: REDSTONE + E: + minecraft_type: REDSTONE + F: minecraft_type: REDSTONE +multi_power_cable_recipe: + result: + nexo_item: multi_power_cable + amount: 1 + ingredients: + A: + minecraft_type: COPPER_INGOT + B: + minecraft_type: COPPER_INGOT + C: + minecraft_type: COPPER_INGOT + D: + minecraft_type: COPPER_INGOT + auto_smelter_recipe: result: nexo_item: auto_smelter amount: 1 ingredients: A: - amount: 3 minecraft_type: IRON_INGOT B: - amount: 3 - minecraft_type: REDSTONE + minecraft_type: IRON_INGOT C: - amount: 1 + minecraft_type: IRON_INGOT + D: + minecraft_type: REDSTONE + E: + minecraft_type: REDSTONE + F: + minecraft_type: REDSTONE + G: minecraft_type: FURNACE diff --git a/src/test/kotlin/com/coderjoe/atlas/AtlasPluginTest.kt b/src/test/kotlin/com/coderjoe/atlas/AtlasPluginTest.kt index e1d9949..c0c656a 100644 --- a/src/test/kotlin/com/coderjoe/atlas/AtlasPluginTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/AtlasPluginTest.kt @@ -30,7 +30,7 @@ class AtlasPluginTest { @Test fun `power system initializes with 27 block types`() { TestHelper.initPowerFactory() - assertEquals(27, PowerBlockFactory.getRegisteredBlockIds().size) + assertEquals(39, PowerBlockFactory.getRegisteredBlockIds().size) } @Test diff --git a/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt b/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt index ca8a49b..de4fddd 100644 --- a/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt +++ b/src/test/kotlin/com/coderjoe/atlas/TestHelper.kt @@ -20,6 +20,7 @@ import com.coderjoe.atlas.power.block.LavaGenerator import com.coderjoe.atlas.power.block.PowerCable import com.coderjoe.atlas.power.block.SmallBattery import com.coderjoe.atlas.power.block.SmallDrill +import com.coderjoe.atlas.power.block.MultiPowerCable import com.coderjoe.atlas.power.block.SmallSolarPanel import io.mockk.* import org.bukkit.Location @@ -171,7 +172,8 @@ object TestHelper { PowerBlockFactory.registerFromDescriptors(listOf( SmallSolarPanel.descriptor, SmallDrill.descriptor, SmallBattery.descriptor, PowerCable.descriptor, - LavaGenerator.descriptor, AutoSmelter.descriptor + LavaGenerator.descriptor, AutoSmelter.descriptor, + MultiPowerCable.descriptor )) } diff --git a/src/test/kotlin/com/coderjoe/atlas/power/MultiPowerCableTest.kt b/src/test/kotlin/com/coderjoe/atlas/power/MultiPowerCableTest.kt new file mode 100644 index 0000000..eac3b16 --- /dev/null +++ b/src/test/kotlin/com/coderjoe/atlas/power/MultiPowerCableTest.kt @@ -0,0 +1,207 @@ +package com.coderjoe.atlas.power + +import com.coderjoe.atlas.TestHelper +import com.coderjoe.atlas.TestHelper.callPowerUpdate +import com.coderjoe.atlas.power.block.MultiPowerCable +import com.coderjoe.atlas.power.block.SmallBattery +import org.bukkit.Location +import org.bukkit.block.BlockFace +import org.junit.jupiter.api.* +import org.junit.jupiter.api.Assertions.* + +class MultiPowerCableTest { + + @BeforeEach + fun setup() { + TestHelper.setup() + } + + @AfterEach + fun teardown() { + TestHelper.teardown() + } + + @Test + fun `multi power cable has correct facing`() { + val cable = MultiPowerCable(TestHelper.createLocation(), BlockFace.NORTH) + assertEquals(BlockFace.NORTH, cable.facing) + } + + @Test + fun `visual state unpowered matches facing`() { + for ((face, id) in MultiPowerCable.DIRECTIONAL_IDS) { + val cable = MultiPowerCable(TestHelper.createLocation(), face) + cable.currentPower = 0 + assertEquals(id, cable.getVisualStateBlockId()) + } + } + + @Test + fun `visual state powered matches facing`() { + for ((face, id) in MultiPowerCable.POWERED_IDS) { + val cable = MultiPowerCable(TestHelper.createLocation(), face) + cable.currentPower = 5 + assertEquals(id, cable.getVisualStateBlockId()) + } + } + + @Test + fun `base block ID is multi_power_cable`() { + val cable = MultiPowerCable(TestHelper.createLocation(), BlockFace.SOUTH) + assertEquals("multi_power_cable", cable.baseBlockId) + } + + @Test + fun `descriptor has correct properties`() { + val desc = MultiPowerCable.descriptor + assertEquals("multi_power_cable", desc.baseBlockId) + assertEquals("Multi Power Cable", desc.displayName) + assertEquals(12, desc.allRegistrableIds.size) + for (id in MultiPowerCable.DIRECTIONAL_IDS.values) { + assertTrue(desc.allRegistrableIds.contains(id), "Missing unpowered ID: $id") + } + for (id in MultiPowerCable.POWERED_IDS.values) { + assertTrue(desc.allRegistrableIds.contains(id), "Missing powered ID: $id") + } + } + + @Test + fun `descriptor has directional placement`() { + val desc = MultiPowerCable.descriptor + assertEquals(com.coderjoe.atlas.core.PlacementType.DIRECTIONAL, desc.placementType) + assertEquals(6, desc.directionalVariants.size) + } + + @Test + fun `facingFromBlockId returns correct facing for unpowered IDs`() { + assertEquals(BlockFace.NORTH, MultiPowerCable.facingFromBlockId("multi_power_cable_north")) + assertEquals(BlockFace.SOUTH, MultiPowerCable.facingFromBlockId("multi_power_cable_south")) + assertEquals(BlockFace.EAST, MultiPowerCable.facingFromBlockId("multi_power_cable_east")) + assertEquals(BlockFace.WEST, MultiPowerCable.facingFromBlockId("multi_power_cable_west")) + assertEquals(BlockFace.UP, MultiPowerCable.facingFromBlockId("multi_power_cable_up")) + assertEquals(BlockFace.DOWN, MultiPowerCable.facingFromBlockId("multi_power_cable_down")) + } + + @Test + fun `facingFromBlockId returns correct facing for powered IDs`() { + assertEquals(BlockFace.NORTH, MultiPowerCable.facingFromBlockId("multi_power_cable_north_powered")) + assertEquals(BlockFace.SOUTH, MultiPowerCable.facingFromBlockId("multi_power_cable_south_powered")) + assertEquals(BlockFace.EAST, MultiPowerCable.facingFromBlockId("multi_power_cable_east_powered")) + assertEquals(BlockFace.WEST, MultiPowerCable.facingFromBlockId("multi_power_cable_west_powered")) + assertEquals(BlockFace.UP, MultiPowerCable.facingFromBlockId("multi_power_cable_up_powered")) + assertEquals(BlockFace.DOWN, MultiPowerCable.facingFromBlockId("multi_power_cable_down_powered")) + } + + @Test + fun `facingFromBlockId returns null for unknown ID`() { + assertNull(MultiPowerCable.facingFromBlockId("multi_power_cable_diagonal")) + assertNull(MultiPowerCable.facingFromBlockId("unknown")) + } + + @Test + fun `all directional IDs are registered`() { + TestHelper.initPowerFactory() + for (id in MultiPowerCable.DIRECTIONAL_IDS.values) { + assertTrue(PowerBlockFactory.isRegistered(id), "Missing multi power cable ID: $id") + } + } + + @Test + fun `all powered IDs are registered`() { + TestHelper.initPowerFactory() + for (id in MultiPowerCable.POWERED_IDS.values) { + assertTrue(PowerBlockFactory.isRegistered(id), "Missing multi power cable powered ID: $id") + } + } + + @Test + fun `factory creates MultiPowerCable from directional ID`() { + TestHelper.initPowerFactory() + val block = PowerBlockFactory.createPowerBlock("multi_power_cable_north", TestHelper.createLocation(), BlockFace.NORTH) + assertTrue(block is MultiPowerCable) + assertEquals(BlockFace.NORTH, block!!.facing) + } + + @Test + fun `max storage is 10`() { + val cable = MultiPowerCable(TestHelper.createLocation(), BlockFace.NORTH) + assertEquals(10, cable.maxStorage) + } + + @Test + fun `pulls power from behind`() { + val registry = PowerBlockRegistry(TestHelper.mockPlugin) + val cableLoc = TestHelper.createLocation(0.0, 64.0, 0.0) + val cable = MultiPowerCable(cableLoc, BlockFace.NORTH) + TestHelper.addToRegistry(registry, cable, "multi_power_cable_north") + + // Place a battery behind (south, opposite of north-facing) + val batteryLoc = TestHelper.createLocation(0.0, 64.0, 1.0) + val battery = SmallBattery(batteryLoc, BlockFace.NORTH) + battery.currentPower = 5 + TestHelper.addToRegistry(registry, battery, "small_battery") + + cable.callPowerUpdate() + + assertTrue(cable.currentPower > 0, "Cable should have pulled power") + assertTrue(battery.currentPower < 5, "Battery should have less power") + } + + @Test + fun `distributes power to multiple outputs`() { + val registry = PowerBlockRegistry(TestHelper.mockPlugin) + val cableLoc = TestHelper.createLocation(0.0, 64.0, 0.0) + val cable = MultiPowerCable(cableLoc, BlockFace.NORTH) + cable.currentPower = 5 + TestHelper.addToRegistry(registry, cable, "multi_power_cable_north") + + // Place batteries on output faces (not behind/south) + val eastBatteryLoc = TestHelper.createLocation(1.0, 64.0, 0.0) + val eastBattery = SmallBattery(eastBatteryLoc, BlockFace.WEST) + TestHelper.addToRegistry(registry, eastBattery, "small_battery") + + val westBatteryLoc = TestHelper.createLocation(-1.0, 64.0, 0.0) + val westBattery = SmallBattery(westBatteryLoc, BlockFace.EAST) + TestHelper.addToRegistry(registry, westBattery, "small_battery_east") + + val northBatteryLoc = TestHelper.createLocation(0.0, 64.0, -1.0) + val northBattery = SmallBattery(northBatteryLoc, BlockFace.SOUTH) + TestHelper.addToRegistry(registry, northBattery, "small_battery_south") + + cable.callPowerUpdate() + + assertTrue(eastBattery.currentPower > 0, "East battery should have received power") + assertTrue(westBattery.currentPower > 0, "West battery should have received power") + assertTrue(northBattery.currentPower > 0, "North battery should have received power") + assertEquals(2, cable.currentPower, "Cable should have distributed 3 power (1 to each)") + } + + @Test + fun `does not exceed max storage when pulling power`() { + val registry = PowerBlockRegistry(TestHelper.mockPlugin) + val cableLoc = TestHelper.createLocation(0.0, 64.0, 0.0) + val cable = MultiPowerCable(cableLoc, BlockFace.NORTH) + cable.currentPower = 10 // Already full + TestHelper.addToRegistry(registry, cable, "multi_power_cable_north") + + val batteryLoc = TestHelper.createLocation(0.0, 64.0, 1.0) + val battery = SmallBattery(batteryLoc, BlockFace.NORTH) + battery.currentPower = 5 + TestHelper.addToRegistry(registry, battery, "small_battery") + + cable.callPowerUpdate() + + assertEquals(10, cable.maxStorage) + assertEquals(5, battery.currentPower, "Battery should not lose power when cable is full") + } + + @Test + fun `does not crash with no adjacent blocks`() { + PowerBlockRegistry(TestHelper.mockPlugin) + val cable = MultiPowerCable(TestHelper.createLocation(), BlockFace.NORTH) + + assertDoesNotThrow { + cable.callPowerUpdate() + } + } +} diff --git a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockInitializerTest.kt b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockInitializerTest.kt index 981aa33..e2f5b7c 100644 --- a/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockInitializerTest.kt +++ b/src/test/kotlin/com/coderjoe/atlas/power/PowerBlockInitializerTest.kt @@ -26,8 +26,8 @@ class PowerBlockRegistrationTest { TestHelper.initPowerFactory() val ids = PowerBlockFactory.getRegisteredBlockIds() - // 1 solar + 6 drill + 4 battery + 6 cable + 2 lava generator + 8 auto smelter = 27 - assertEquals(27, ids.size) + // 1 solar + 6 drill + 4 battery + 6 cable + 2 lava generator + 8 auto smelter + 12 multi power cable = 39 + assertEquals(39, ids.size) } @Test