From 80130a68e1ff19186e753d81b89c2a34551a8341 Mon Sep 17 00:00:00 2001 From: ionut Date: Mon, 27 Apr 2026 19:04:26 +0300 Subject: [PATCH] rip capacitors (WIP refactor) if anyone touches this while I'm working on it, I will find you, and I will refactor you too --- .../neoflock/neocomputers/block/Capacitor.kt | 16 ++- .../neoflock/neocomputers/block/CaseBlock.kt | 2 +- .../neocomputers/block/DeviceBlock.kt | 115 ++++++++++++++++++ .../neoflock/neocomputers/block/RedstoneIO.kt | 10 +- .../neocomputers/entity/BlockEntities.kt | 7 +- .../neocomputers/entity/CaseBlockEntity.kt | 11 +- 6 files changed, 140 insertions(+), 21 deletions(-) create mode 100644 src/main/kotlin/org/neoflock/neocomputers/block/DeviceBlock.kt diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/Capacitor.kt b/src/main/kotlin/org/neoflock/neocomputers/block/Capacitor.kt index ebc0b82..58dc9db 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/block/Capacitor.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/block/Capacitor.kt @@ -2,10 +2,12 @@ package org.neoflock.neocomputers.block import net.minecraft.client.player.LocalPlayer import net.minecraft.core.BlockPos +import net.minecraft.core.Direction import net.minecraft.core.HolderLookup import net.minecraft.nbt.CompoundTag import net.minecraft.network.chat.OutgoingChatMessage import net.minecraft.network.chat.PlayerChatMessage +import net.minecraft.server.level.ServerPlayer import net.minecraft.world.InteractionResult import net.minecraft.world.entity.player.Player import net.minecraft.world.level.Level @@ -18,13 +20,17 @@ import org.neoflock.neocomputers.network.DeviceNode import org.neoflock.neocomputers.network.PowerRole import kotlin.math.min -open class CapacitorEntity(val capacity: Long, type: BlockEntityType<*>, pos: BlockPos, state: BlockState) : NodeBlockEntity(type, pos, state) { +open class CapacitorEntity(val capacity: Long, type: BlockEntityType<*>, pos: BlockPos, state: BlockState) : DeviceBlockEntity(type, pos, state) { - override val deviceNode = object : DeviceNode() { + val deviceNode = object : DeviceNode() { override var powerRole = PowerRole.STORAGE override var energyCapacity: Long = capacity } + // TODO: cache list + override fun getDeviceNodes() = listOf(deviceNode) + override fun getNodeFromSide(directionToRequester: Direction) = deviceNode + override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) { super.loadAdditional(compoundTag, provider) deviceNode.energy = min(compoundTag.getLong("energy"), deviceNode.energyCapacity) @@ -58,12 +64,12 @@ class CapacitorBlock(val tier: Int) : NodeBlock() { player: Player, blockHitResult: BlockHitResult ): InteractionResult { - if(level.isClientSide()) { - val p = player as LocalPlayer + if(!level.isClientSide()) { + val p = player as ServerPlayer val ent = level.getBlockEntity(blockPos) if(ent is CapacitorEntity) { if(p.isCrouching) ent.deviceNode.giveEnergy(1) - val msg = PlayerChatMessage.system("energy: ${ent.deviceNode.energy} / ${ent.capacity} (${ent.computeEdges().size} edges, ${ent.deviceNode.getReachable().size} connected)") + val msg = PlayerChatMessage.system("energy: ${ent.deviceNode.energy} / ${ent.capacity} (${ent.deviceNode.connections.size} connections, ${ent.deviceNode.getReachable().size} connected)") p.sendSystemMessage(OutgoingChatMessage.create(msg).content()) } } diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt b/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt index 6fcd9c5..3e22053 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/block/CaseBlock.kt @@ -64,7 +64,7 @@ class CaseBlock() : NodeBlock(Properties.of().sound(SoundType.METAL).lightLevel( blockPos: BlockPos, direction: Direction ): Int { - return getMachine(blockGetter, blockPos).redstoneOut[dirToIdx(direction.opposite)] + return getMachine(blockGetter, blockPos).redstoneOut[direction.opposite.ordinal] } override fun onPlace( diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/DeviceBlock.kt b/src/main/kotlin/org/neoflock/neocomputers/block/DeviceBlock.kt new file mode 100644 index 0000000..64a1e92 --- /dev/null +++ b/src/main/kotlin/org/neoflock/neocomputers/block/DeviceBlock.kt @@ -0,0 +1,115 @@ +package org.neoflock.neocomputers.block + +import net.minecraft.core.BlockPos +import net.minecraft.core.Direction +import net.minecraft.world.level.Level +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.EntityBlock +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.BlockEntityTicker +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState +import org.neoflock.neocomputers.network.DeviceNode +import org.neoflock.neocomputers.network.Networking + +abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): BlockEntity(type, pos, state) { + val connetionsInDir = MutableList(Direction.entries.size) { HashSet() } + + abstract fun getDeviceNodes(): List + + // Gets, if applicable, the node from a direction. + // The direction is from this block entity to the original requester, + // so it is Direction.UP if we asked from the one on the top side. + abstract fun getNodeFromSide(directionToRequester: Direction): DeviceNode? + + open fun initNetworking(): DeviceBlockEntity { + getDeviceNodes().forEach { Networking.addNode(it) } + Direction.entries.forEach { handleConnectionsFor(it) } + return this + } + + open fun getCurrentlyConnectedNodesIn(direction: Direction): HashSet { + val ent = level?.getBlockEntity(blockPos.relative(direction)) + val connected = HashSet() + if(ent is DeviceBlockEntity) { + val node = ent.getNodeFromSide(direction.opposite) + if(node != null) connected.add(node) + } + return connected + } + + // TODO: rethink this shi so sharing a node on 2 different sides doesn't make connections require mutually exclusive conditions + // TODO: actually like, rethink the whole class so far + + open fun handleConnectionsFor(direction: Direction) { + // refuse connections on no node to reduce CPU load + val node = getNodeFromSide(direction.opposite) ?: return + val old = connetionsInDir[direction.ordinal] + val now = getCurrentlyConnectedNodesIn(direction) + + // TODO: optimize this hellscape + + val toKill = HashSet() + old.forEach { + if(it !in now) toKill.add(it) + } + toKill.forEach { node.disconnectFrom(it) } + now.forEach { + if(it !in old) node.connectTo(it) + } + connetionsInDir[direction.ordinal] = now + } + + // TODO: optimize this sometime before our test computers melt + open fun tickDevice() { + // Handles device connections and sync here + + // Process connections + Direction.entries.forEach { + handleConnectionsFor(it) + } + } + + override fun setRemoved() { + super.setRemoved() + getDeviceNodes().forEach { Networking.removeNode(it) } + } +} + +abstract class DeviceBlock(properties: Properties = Properties.of()): BaseBlock(properties), EntityBlock { + override fun getTicker( + level: Level, + state: BlockState, + blockEntityType: BlockEntityType + ): BlockEntityTicker { + return object : BlockEntityTicker { + override fun tick(level: Level, blockPos: BlockPos, blockState: BlockState, blockEntity: T & Any) { + if(blockEntity !is DeviceBlockEntity) return + blockEntity.tickDevice() + } + } + } + + override fun onPlace(state: BlockState, level: Level, pos: BlockPos, oldState: BlockState, movedByPiston: Boolean) { + super.onPlace(state, level, pos, oldState, movedByPiston) + val ent = level.getBlockEntity(pos) + if(ent is DeviceBlockEntity) { + ent.initNetworking() + } + } + + override fun neighborChanged( + state: BlockState, + level: Level, + pos: BlockPos, + neighborBlock: Block, + neighborPos: BlockPos, + movedByPiston: Boolean + ) { + super.neighborChanged(state, level, pos, neighborBlock, neighborPos, movedByPiston) + val ent = level.getBlockEntity(pos) + if(ent is DeviceBlockEntity) { + ent.handleConnectionsFor(Direction.getNearest(neighborPos.center.subtract(pos.center))) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/neoflock/neocomputers/block/RedstoneIO.kt b/src/main/kotlin/org/neoflock/neocomputers/block/RedstoneIO.kt index b106a0f..beb213f 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/block/RedstoneIO.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/block/RedstoneIO.kt @@ -15,8 +15,6 @@ import org.neoflock.neocomputers.entity.BlockEntities import org.neoflock.neocomputers.network.Networking import org.neoflock.neocomputers.network.DeviceNode -fun dirToIdx(direction: Direction) = Direction.entries.indexOf(direction) - class RedstoneIOEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEntity(BlockEntities.REDSTONEIO_ENTITY.get(), blockPos, blockState) { val redstoneIn = Array(Direction.entries.size) {0} val redstoneOut = Array(Direction.entries.size) {0} @@ -29,7 +27,7 @@ class RedstoneIOEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnt fun refetch(dir: Direction) { val src = blockPos.offset(dir.stepX, dir.stepY, dir.stepZ) val cur = level?.getSignal(src, dir) ?: 0 - val idx = dirToIdx(dir) + val idx = dir.ordinal if(redstoneIn[idx] != cur) { onRedstoneSignalChanged(dir, redstoneIn[idx], cur) } @@ -41,7 +39,7 @@ class RedstoneIOEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnt } fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) { - Networking.emitMessage(deviceNode, Networking.ComputerUncheckedSignal(deviceNode, "redstone_changed", arrayOf(deviceNode.address.toString(), dirToIdx(dir), oldValue, newValue))) + Networking.emitMessage(deviceNode, Networking.ComputerUncheckedSignal(deviceNode, "redstone_changed", arrayOf(deviceNode.address.toString(), dir.ordinal, oldValue, newValue))) NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue") } } @@ -67,7 +65,7 @@ class RedstoneIOBlock(): NodeBlock(Properties.of().isRedstoneConductor { state, ): Int { val redstoneIO = getRedstoneIO(blockGetter, blockPos) if(redstoneIO != null) { - return redstoneIO.redstoneOut[dirToIdx(direction.opposite)] + return redstoneIO.redstoneOut[direction.opposite.ordinal] } return super.getSignal(blockState, blockGetter, blockPos, direction) } @@ -125,7 +123,7 @@ class RedstoneIOBlock(): NodeBlock(Properties.of().isRedstoneConductor { state, val redio = getRedstoneIO(level, blockPos) val dir = blockHitResult.direction if (redio != null) { - val idx = dirToIdx(dir) + val idx = dir.ordinal redio.redstoneOut[idx]++ redio.redstoneOut[idx] %= 16 NeoComputers.LOGGER.info("outputting redstone level ${redio.redstoneOut[idx]} on ${dir.name}") diff --git a/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt b/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt index 801a9dc..cd3173d 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/entity/BlockEntities.kt @@ -88,9 +88,10 @@ object BlockEntities { } fun registerPowerBlocks() { - PowerManager.registerPowerBlockEntity(CAPACITOR_ENTITY.get()) - PowerManager.registerPowerBlockEntity(CAPACITOR2_ENTITY.get()) - PowerManager.registerPowerBlockEntity(CAPACITOR3_ENTITY.get()) + // TODO: function for the new DeviceBlockEntity + //PowerManager.registerPowerBlockEntity(CAPACITOR_ENTITY.get()) + //PowerManager.registerPowerBlockEntity(CAPACITOR2_ENTITY.get()) + //PowerManager.registerPowerBlockEntity(CAPACITOR3_ENTITY.get()) PowerManager.registerPowerBlockEntity(SOLARGEN_ENTITY.get()) PowerManager.registerPowerBlockEntity(COMBUSTGEN_ENTITY.get()) PowerManager.registerPowerBlockEntity(CASE_ENTITY.get()) diff --git a/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt b/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt index ea0535c..7a8f4f4 100644 --- a/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt +++ b/src/main/kotlin/org/neoflock/neocomputers/entity/CaseBlockEntity.kt @@ -22,7 +22,6 @@ import org.neoflock.neocomputers.NeoComputers import org.neoflock.neocomputers.block.CaseBlock import org.neoflock.neocomputers.block.NodeBlockEntity import org.neoflock.neocomputers.block.NodeSynchronizer -import org.neoflock.neocomputers.block.dirToIdx import org.neoflock.neocomputers.gui.menu.CaseMenu import org.neoflock.neocomputers.item.ComponentItem import org.neoflock.neocomputers.network.DeviceNode @@ -95,7 +94,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti fun refetchRedstone(dir: Direction) { val src = blockPos.offset(dir.stepX, dir.stepY, dir.stepZ) val cur = level?.getSignal(src, dir) ?: 0 - val idx = dirToIdx(dir) + val idx = dir.ordinal if(redstoneIn[idx] != cur) { onRedstoneSignalChanged(dir, redstoneIn[idx], cur) } @@ -118,7 +117,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) { sendMachineEvent(MachineRedstoneEvent(this, dir, oldValue, newValue)) - Networking.emitMessage(deviceNode, Networking.ComputerUncheckedSignal(deviceNode, "redstone_changed", arrayOf(deviceNode.address.toString(), dirToIdx(dir), oldValue, newValue))) + Networking.emitMessage(deviceNode, Networking.ComputerUncheckedSignal(deviceNode, "redstone_changed", arrayOf(deviceNode.address.toString(), dir.ordinal, oldValue, newValue))) NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue") if(oldValue == 0) { // Rising edge @@ -208,12 +207,12 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti override fun getMachineNode() = deviceNode - override fun getRedstoneInput(direction: Direction): Int = redstoneIn[dirToIdx(direction)] + override fun getRedstoneInput(direction: Direction): Int = redstoneIn[direction.ordinal] - override fun getRedstoneOutput(direction: Direction): Int = redstoneOut[dirToIdx(direction)] + override fun getRedstoneOutput(direction: Direction): Int = redstoneOut[direction.ordinal] override fun setRedstoneOutput(direction: Direction, newValue: Int): Int { - val idx = dirToIdx(direction) + val idx = direction.ordinal val old = redstoneOut[idx] redstoneOut[idx] = newValue return old