Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/main/kotlin/com/coderjoe/atlas/Atlas.kt
Original file line number Diff line number Diff line change
Expand Up @@ -181,15 +181,19 @@ class Atlas : JavaPlugin() {
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.MultiPowerCable.descriptor
com.coderjoe.atlas.power.block.MultiPowerCable.descriptor,
com.coderjoe.atlas.power.block.CobblestoneGenerator.descriptor,
com.coderjoe.atlas.power.block.ObsidianGenerator.descriptor,
com.coderjoe.atlas.power.block.PowerMerger.descriptor
).associateBy { it.baseBlockId }
}

private fun fluidDescriptors(): Map<String, com.coderjoe.atlas.core.BlockDescriptor> {
return listOf(
com.coderjoe.atlas.fluid.block.FluidPump.descriptor,
com.coderjoe.atlas.fluid.block.FluidPipe.descriptor,
com.coderjoe.atlas.fluid.block.FluidContainer.descriptor
com.coderjoe.atlas.fluid.block.FluidContainer.descriptor,
com.coderjoe.atlas.fluid.block.FluidMerger.descriptor
).associateBy { it.baseBlockId }
}
}
4 changes: 4 additions & 0 deletions src/main/kotlin/com/coderjoe/atlas/fluid/FluidBlockDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.coderjoe.atlas.core.AtlasBlockDialog
import com.coderjoe.atlas.core.BlockRegistry
import com.coderjoe.atlas.fluid.block.FluidContainer
import com.coderjoe.atlas.fluid.block.FluidPipe
import com.coderjoe.atlas.fluid.block.FluidMerger
import com.coderjoe.atlas.fluid.block.FluidPump
import io.papermc.paper.dialog.Dialog
import io.papermc.paper.registry.data.dialog.ActionButton
Expand Down Expand Up @@ -71,6 +72,7 @@ object FluidBlockDialog {
is FluidPump -> "Fluid Pump"
is FluidPipe -> "Fluid Pipe (${fluidBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})"
is FluidContainer -> "Fluid Container (${fluidBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})"
is FluidMerger -> "Fluid Merger (${fluidBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})"
else -> "Fluid Block"
}

Expand Down Expand Up @@ -107,6 +109,8 @@ object FluidBlockDialog {
.color(NamedTextColor.GRAY)
is FluidContainer -> Component.text("Container - stores up to ${FluidContainer.MAX_CAPACITY} units of fluid")
.color(NamedTextColor.GRAY)
is FluidMerger -> Component.text("Merger - merges fluid from all sides, outputs in facing direction")
.color(NamedTextColor.GRAY)
else -> Component.text("Fluid block")
.color(NamedTextColor.GRAY)
}
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidContainer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@ class FluidContainer(location: Location, override val facing: BlockFace) : Fluid
}
}
}
is FluidMerger -> {
if (source.hasFluid()) {
val fluid = source.removeFluid()
if (storeFluid(fluid)) {
plugin.logger.atlasInfo("FluidContainer at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidMerger")
} else {
source.storeFluid(fluid)
}
}
}
}
}

Expand Down
117 changes: 117 additions & 0 deletions src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidMerger.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.coderjoe.atlas.fluid.block

import com.coderjoe.atlas.atlasInfo
import com.coderjoe.atlas.core.BlockDescriptor
import com.coderjoe.atlas.core.PlacementType
import com.coderjoe.atlas.fluid.FluidBlock
import com.coderjoe.atlas.fluid.FluidBlockRegistry
import com.coderjoe.atlas.fluid.FluidType
import org.bukkit.Location
import org.bukkit.block.BlockFace

class FluidMerger(location: Location, override val facing: BlockFace) : FluidBlock(location) {

override val updateIntervalTicks: Long = 20L

companion object {
const val BLOCK_ID = "fluid_merger"

val DIRECTIONAL_IDS = mapOf(
BlockFace.NORTH to "fluid_merger_north",
BlockFace.SOUTH to "fluid_merger_south",
BlockFace.EAST to "fluid_merger_east",
BlockFace.WEST to "fluid_merger_west",
BlockFace.UP to "fluid_merger_up",
BlockFace.DOWN to "fluid_merger_down"
)

val WATER_FILLED_IDS = mapOf(
BlockFace.NORTH to "fluid_merger_north_filled",
BlockFace.SOUTH to "fluid_merger_south_filled",
BlockFace.EAST to "fluid_merger_east_filled",
BlockFace.WEST to "fluid_merger_west_filled",
BlockFace.UP to "fluid_merger_up_filled",
BlockFace.DOWN to "fluid_merger_down_filled"
)

val LAVA_FILLED_IDS = mapOf(
BlockFace.NORTH to "fluid_merger_north_filled_lava",
BlockFace.SOUTH to "fluid_merger_south_filled_lava",
BlockFace.EAST to "fluid_merger_east_filled_lava",
BlockFace.WEST to "fluid_merger_west_filled_lava",
BlockFace.UP to "fluid_merger_up_filled_lava",
BlockFace.DOWN to "fluid_merger_down_filled_lava"
)

val ID_TO_FACING = DIRECTIONAL_IDS.entries.associate { (face, id) -> id to face }

fun facingFromBlockId(blockId: String): BlockFace? = ID_TO_FACING[blockId]

val descriptor = BlockDescriptor(
baseBlockId = BLOCK_ID,
displayName = "Fluid Merger",
description = "Merger - merges fluid from all sides, outputs in facing direction",
placementType = PlacementType.DIRECTIONAL,
directionalVariants = DIRECTIONAL_IDS,
allRegistrableIds = DIRECTIONAL_IDS.values.toList() + WATER_FILLED_IDS.values.toList() + LAVA_FILLED_IDS.values.toList(),
constructor = { loc, facing -> FluidMerger(loc, facing) }
)
}

override val baseBlockId: String = BLOCK_ID

override fun getVisualStateBlockId(): String = when (storedFluid) {
FluidType.WATER -> WATER_FILLED_IDS[facing]!!
FluidType.LAVA -> LAVA_FILLED_IDS[facing]!!
FluidType.NONE -> DIRECTIONAL_IDS[facing]!!
}

override fun fluidUpdate() {
if (hasFluid()) return

val registry = FluidBlockRegistry.instance ?: return

// Pull fluid from all faces except the output (facing) direction
val inputFaces = listOf(BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST, BlockFace.UP, BlockFace.DOWN)
.filter { it != facing }

for (face in inputFaces) {
val source = registry.getAdjacentFluidBlock(location, face) ?: continue

when (source) {
is FluidPump -> {
if (source.canRemoveFluidFrom(face.oppositeFace) && source.hasFluid()) {
val fluid = source.removeFluid()
storeFluid(fluid)
plugin.logger.atlasInfo("FluidMerger at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidPump at ${face.name}")
return
}
}
is FluidPipe -> {
if (source.hasFluid()) {
val fluid = source.removeFluid()
storeFluid(fluid)
plugin.logger.atlasInfo("FluidMerger at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidPipe at ${face.name}")
return
}
}
is FluidContainer -> {
if (source.canRemoveFluidFrom(face.oppositeFace) && source.hasFluid()) {
val fluid = source.removeFluid()
storeFluid(fluid)
plugin.logger.atlasInfo("FluidMerger at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidContainer at ${face.name}")
return
}
}
is FluidMerger -> {
if (source.hasFluid()) {
val fluid = source.removeFluid()
storeFluid(fluid)
plugin.logger.atlasInfo("FluidMerger at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidMerger at ${face.name}")
return
}
}
}
}
}
}
7 changes: 7 additions & 0 deletions src/main/kotlin/com/coderjoe/atlas/fluid/block/FluidPipe.kt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ class FluidPipe(location: Location, override val facing: BlockFace) : FluidBlock
plugin.logger.atlasInfo("FluidPipe at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidContainer")
}
}
is FluidMerger -> {
if (source.hasFluid()) {
val fluid = source.removeFluid()
storeFluid(fluid)
plugin.logger.atlasInfo("FluidPipe at ${location.blockX},${location.blockY},${location.blockZ} pulled ${fluid.name} from FluidMerger")
}
}
}
}
}
12 changes: 12 additions & 0 deletions src/main/kotlin/com/coderjoe/atlas/power/PowerBlockDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ 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.CobblestoneGenerator
import com.coderjoe.atlas.power.block.ObsidianGenerator
import com.coderjoe.atlas.power.block.PowerMerger
import com.coderjoe.atlas.power.block.SmallSolarPanel
import io.papermc.paper.dialog.Dialog
import io.papermc.paper.registry.data.dialog.ActionButton
Expand Down Expand Up @@ -129,6 +132,9 @@ object PowerBlockDialog {
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() }})"
is CobblestoneGenerator -> "Cobblestone Generator"
is ObsidianGenerator -> "Obsidian Generator"
is PowerMerger -> "Power Merger (${powerBlock.facing.name.lowercase().replaceFirstChar { it.uppercase() }})"
else -> "Power Block"
}

Expand Down Expand Up @@ -177,6 +183,12 @@ object PowerBlockDialog {
.color(NamedTextColor.GRAY)
is MultiPowerCable -> Component.text("Cable - distributes power to all adjacent faces")
.color(NamedTextColor.GRAY)
is CobblestoneGenerator -> Component.text("Machine - consumes ${CobblestoneGenerator.POWER_COST} power + water + lava → cobblestone")
.color(NamedTextColor.GRAY)
is ObsidianGenerator -> Component.text("Machine - consumes ${ObsidianGenerator.POWER_COST} power + water + lava → obsidian")
.color(NamedTextColor.GRAY)
is PowerMerger -> Component.text("Cable - merges power from all sides, outputs in facing direction")
.color(NamedTextColor.GRAY)
else -> Component.text("Power block")
.color(NamedTextColor.GRAY)
}
Expand Down
118 changes: 118 additions & 0 deletions src/main/kotlin/com/coderjoe/atlas/power/block/CobblestoneGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
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.fluid.FluidBlockRegistry
import com.coderjoe.atlas.fluid.FluidType
import com.coderjoe.atlas.fluid.block.FluidContainer
import com.coderjoe.atlas.fluid.block.FluidMerger
import com.coderjoe.atlas.fluid.block.FluidPipe
import com.coderjoe.atlas.fluid.block.FluidPump
import com.coderjoe.atlas.power.PowerBlock
import com.coderjoe.atlas.power.PowerBlockRegistry
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.block.BlockFace
import org.bukkit.inventory.ItemStack

class CobblestoneGenerator(location: Location) : PowerBlock(location, maxStorage = 2) {

override val canReceivePower: Boolean = true
override val updateIntervalTicks: Long = 20L

companion object {
const val BLOCK_ID = "cobblestone_generator"
const val BLOCK_ID_ACTIVE = "cobblestone_generator_active"
const val POWER_COST = 2

private val ADJACENT_FACES = listOf(
BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST,
BlockFace.WEST, BlockFace.UP, BlockFace.DOWN
)

val descriptor = BlockDescriptor(
baseBlockId = BLOCK_ID,
displayName = "Cobblestone Generator",
description = "Machine - consumes $POWER_COST power + water + lava → cobblestone",
placementType = PlacementType.SIMPLE,
directionalVariants = emptyMap(),
allRegistrableIds = listOf(BLOCK_ID, BLOCK_ID_ACTIVE),
constructor = { loc, _ -> CobblestoneGenerator(loc) }
)
}

override val baseBlockId: String = BLOCK_ID

override fun getVisualStateBlockId(): String = when {
currentPower >= POWER_COST -> BLOCK_ID_ACTIVE
else -> BLOCK_ID
}

override fun powerUpdate() {
// Pull power from adjacent blocks
if (canAcceptPower()) {
val registry = PowerBlockRegistry.instance ?: return
val neighbors = registry.getAdjacentPowerBlocks(location)
for (neighbor in neighbors) {
if (!canAcceptPower()) break
if (neighbor.hasPower()) {
val pulled = neighbor.removePower(1)
if (pulled > 0) {
addPower(pulled)
}
}
}
}

if (currentPower < POWER_COST) return

val fluidRegistry = FluidBlockRegistry.instance ?: return

// Check that BOTH water and lava are available before consuming either
var waterSource: Pair<com.coderjoe.atlas.fluid.FluidBlock, BlockFace>? = null
var lavaSource: Pair<com.coderjoe.atlas.fluid.FluidBlock, BlockFace>? = null

for (face in ADJACENT_FACES) {
val source = fluidRegistry.getAdjacentFluidBlock(location, face) ?: continue
if (waterSource == null && hasFluidAvailable(source, face, FluidType.WATER)) {
waterSource = Pair(source, face)
} else if (lavaSource == null && hasFluidAvailable(source, face, FluidType.LAVA)) {
lavaSource = Pair(source, face)
}
if (waterSource != null && lavaSource != null) break
}

if (waterSource == null || lavaSource == null) return

// Both available — consume atomically
pullFluid(waterSource.first, waterSource.second)
pullFluid(lavaSource.first, lavaSource.second)
removePower(POWER_COST)

val world = location.world ?: return
val dropLocation = location.clone().add(0.5, 1.0, 0.5)
world.dropItemNaturally(dropLocation, ItemStack(Material.COBBLESTONE))

plugin.logger.atlasInfo("CobblestoneGenerator at ${location.blockX},${location.blockY},${location.blockZ} produced 1 cobblestone")
}

private fun hasFluidAvailable(source: com.coderjoe.atlas.fluid.FluidBlock, face: BlockFace, fluidType: FluidType): Boolean {
return when (source) {
is FluidPump -> source.canRemoveFluidFrom(face.oppositeFace) && source.storedFluid == fluidType
is FluidPipe -> source.hasFluid() && source.storedFluid == fluidType
is FluidContainer -> source.canRemoveFluidFrom(face.oppositeFace) && source.storedFluid == fluidType
is FluidMerger -> source.hasFluid() && source.storedFluid == fluidType
else -> false
}
}

private fun pullFluid(source: com.coderjoe.atlas.fluid.FluidBlock, face: BlockFace) {
when (source) {
is FluidPump -> source.removeFluid()
is FluidPipe -> source.removeFluid()
is FluidContainer -> source.removeFluid()
is FluidMerger -> source.removeFluid()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.coderjoe.atlas.core.PlacementType
import com.coderjoe.atlas.fluid.FluidBlockRegistry
import com.coderjoe.atlas.fluid.FluidType
import com.coderjoe.atlas.fluid.block.FluidContainer
import com.coderjoe.atlas.fluid.block.FluidMerger
import com.coderjoe.atlas.fluid.block.FluidPipe
import com.coderjoe.atlas.fluid.block.FluidPump
import com.coderjoe.atlas.power.PowerBlock
Expand Down Expand Up @@ -84,6 +85,12 @@ class LavaGenerator(location: Location) : PowerBlock(location, maxStorage = 50)
return true
}
}
is FluidMerger -> {
if (source.hasFluid() && source.storedFluid == FluidType.LAVA) {
source.removeFluid()
return true
}
}
}
return false
}
Expand Down
Loading
Loading