NodeBlockEntity is dead, long live SingleDeviceBlockEntity + cables function

This commit is contained in:
2026-04-28 17:16:33 +03:00
parent 464584877c
commit 43255b1caf
28 changed files with 495 additions and 537 deletions

View File

@@ -88,12 +88,11 @@ object BlockEntities {
}
fun registerPowerBlocks() {
// 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())
PowerManager.registerPowerDevice(CAPACITOR_ENTITY.get())
PowerManager.registerPowerDevice(CAPACITOR2_ENTITY.get())
PowerManager.registerPowerDevice(CAPACITOR3_ENTITY.get())
PowerManager.registerPowerDevice(SOLARGEN_ENTITY.get())
PowerManager.registerPowerDevice(COMBUSTGEN_ENTITY.get())
PowerManager.registerPowerDevice(CASE_ENTITY.get())
}
}

View File

@@ -2,15 +2,31 @@ package org.neoflock.neocomputers.entity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.world.item.DyeColor
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import org.neoflock.neocomputers.block.CableBlock
import org.neoflock.neocomputers.block.CableBlock.Companion.COLOR
import org.neoflock.neocomputers.block.CableBlock.Companion.getPropByDirection
import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
import org.neoflock.neocomputers.network.DeviceNode
class CableEntity(pos: BlockPos, state: BlockState) : BlockEntity(BlockEntities.CABLE_ENTITY.get(), pos, state) {
class CableEntity(pos: BlockPos, state: BlockState) : SingleDeviceBlockEntity(BlockEntities.CABLE_ENTITY.get(), pos, state) {
override val deviceNode = object : DeviceNode(){}
override fun sendCommitsToClient(level: Level) {
// we have nothing to commit lol
return
}
override fun getNodeFromSide(directionToRequester: Direction): DeviceNode? {
if(CableBlock.shouldConnect(blockPos, blockPos.relative(directionToRequester), level!!)) {
return deviceNode
}
return null
}
override fun setChanged() {
super.setChanged()

View File

@@ -20,8 +20,7 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
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.SingleDeviceBlockEntity
import org.neoflock.neocomputers.gui.menu.CaseMenu
import org.neoflock.neocomputers.item.ComponentItem
import org.neoflock.neocomputers.network.DeviceNode
@@ -33,8 +32,10 @@ import org.neoflock.neocomputers.utils.GenericContainer
import java.time.Duration
import kotlin.math.max
import kotlin.math.min
import org.neoflock.neocomputers.network.NodeSynchronizer
import kotlin.text.ifEmpty
class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEntity(BlockEntities.CASE_ENTITY.get(), blockPos, blockState), MachineEntity, GenericContainer, MenuProvider {
class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlockEntity(BlockEntities.CASE_ENTITY.get(), blockPos, blockState), MachineEntity, GenericContainer, MenuProvider {
val stacks: NonNullList<ItemStack> = NonNullList<ItemStack>.withSize(7, ItemStack.EMPTY)
var isOn = false
@@ -47,45 +48,63 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
override val deviceNode = object : DeviceNode() {
override var powerRole = PowerRole.CONSUMER
override var energyCapacity: Long = 500
}
override fun encodeDownstreamData(packet: FriendlyByteBuf) {
super.encodeDownstreamData(packet)
packet.writeBoolean(isOn)
packet.writeVarInt(diskActivityTime)
packet.writeVarInt(networkActivityTime)
packet.writeUtf(err ?: "")
}
override fun syncWithUpstream(packet: FriendlyByteBuf) {
super.syncWithUpstream(packet)
setRunning(packet.readBoolean())
diskActivityTime = packet.readVarInt()
networkActivityTime = packet.readVarInt()
err = packet.readUtf().ifEmpty { null }
}
override fun processScreenInteraction(player: ServerPlayer, packet: FriendlyByteBuf) {
val c = packet.readByte().toInt()
if(c == 0x01) {
start()
override fun writeFullStateCommit(buf: FriendlyByteBuf) {
super.writeFullStateCommit(buf)
buf.writeUUID(address)
buf.writeBoolean(isOn)
buf.writeVarInt(diskActivityTime)
buf.writeVarInt(networkActivityTime)
buf.writeUtf(err ?: "")
}
if(c == 0x02) {
stop()
}
}
override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {
super.encodeScreenData(player, packet)
packet.writeBoolean(isOn)
packet.writeByteArray((err ?: "").encodeToByteArray())
packet.writeLong(deviceNode.energy)
packet.writeLong(deviceNode.energyCapacity)
packet.writeLong(getMachineMemoryUsed())
packet.writeLong(getMachineMemoryTotal())
packet.writeLong(getMachineComponentsUsed())
packet.writeLong(getMachineComponentsTotal())
packet.writeUtf(arch)
override fun processCommit(buf: FriendlyByteBuf) {
super.processCommit(buf)
Networking.changeNodeAddress(this, buf.readUUID())
setRunning(buf.readBoolean())
diskActivityTime = buf.readVarInt()
networkActivityTime = buf.readVarInt()
err = buf.readUtf().ifEmpty { null }
}
override fun processScreenInteraction(player: ServerPlayer, buf: FriendlyByteBuf) {
super.processScreenInteraction(player, buf)
val c = buf.readByte().toInt()
if(c == 0x01) {
start()
}
if(c == 0x02) {
stop()
}
}
override fun encodeScreenData(player: ServerPlayer, buf: FriendlyByteBuf) {
super.encodeScreenData(player, buf)
buf.writeBoolean(isOn)
buf.writeByteArray((err ?: "").encodeToByteArray())
buf.writeLong(energy)
buf.writeLong(energyCapacity)
buf.writeLong(getMachineMemoryUsed())
buf.writeLong(getMachineMemoryTotal())
buf.writeLong(getMachineComponentsUsed())
buf.writeLong(getMachineComponentsTotal())
buf.writeUtf(arch)
}
override fun tick() {
super.tick()
if (isRunning()) {
if(diskActivityTime > 0) diskActivityTime--
if(networkActivityTime > 0) networkActivityTime--
if(getMachineArchitectures().isEmpty()) {
crash("@neocomputers.errors.ENOCPU")
} else if(getMachineComponentsUsed() > getMachineComponentsTotal()) {
crash("@neocomputers.errors.E2BIG")
} else if (!consumeEnergy(1)) {
crash("@neocomputers.errors.ENOENJ")
}
}
}
}
val redstoneIn = Array(Direction.entries.size) {0}
@@ -154,9 +173,9 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
override fun start(): Boolean {
if(isOn) return true
err = null
val archs = getMachineArchitectures()
val architectures = getMachineArchitectures()
// Beep patterns taken from https://github.com/MightyPirates/OpenComputers/blob/571482db88080d56329e8f8cf0db2a90825bf1d7/src/main/scala/li/cil/oc/server/machine/Machine.scala
if(archs.isEmpty()) {
if(architectures.isEmpty()) {
crash("@neocomputers.errors.ENOCPU")
beepAsync("-..")
return false
@@ -178,9 +197,9 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
beepAsync("-.")
return false
}
if(arch !in archs) {
if(arch !in architectures) {
// Just pick one! TODO: consult EEPROM first
arch = archs.first()
arch = architectures.first()
}
beepAsync(".")
setRunning(true)
@@ -194,10 +213,8 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
}
override fun crash(error: String): Boolean {
if(isOn) {
beepAsync("--")
sendMachineEvent(MachineCrashEvent(this, error))
}
beepAsync("--")
sendMachineEvent(MachineCrashEvent(this, error))
setRunning(false)
err = error
return true
@@ -271,21 +288,4 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
setRunning(false)
super.setRemoved()
}
override fun tickNode(level: Level) {
super.tickNode(level)
if(!level.isClientSide) {
if (isRunning()) {
if(diskActivityTime > 0) diskActivityTime--
if(networkActivityTime > 0) networkActivityTime--
if(getMachineArchitectures().isEmpty()) {
crash("@neocomputers.errors.ENOCPU")
} else if(getMachineComponentsUsed() > getMachineComponentsTotal()) {
crash("@neocomputers.errors.E2BIG")
} else if (!deviceNode.consumeEnergy(1)) {
crash("@neocomputers.errors.ENOENJ")
}
}
}
}
}

View File

@@ -1,6 +1,7 @@
package org.neoflock.neocomputers.entity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList
import net.minecraft.nbt.CompoundTag
@@ -15,16 +16,15 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import org.neoflock.neocomputers.block.CombustionGeneratorBlock
import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
import org.neoflock.neocomputers.gui.menu.CombustionGeneratorMenu
import org.neoflock.neocomputers.network.DeviceNode
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.network.PowerRole
import org.neoflock.neocomputers.utils.GenericContainer
import org.neoflock.neocomputers.utils.ContainerUtils
import kotlin.math.min
class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : NodeBlockEntity(BlockEntities.COMBUSTGEN_ENTITY.get(), blockPos, blockState), GenericContainer, MenuProvider {
class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : SingleDeviceBlockEntity(BlockEntities.COMBUSTGEN_ENTITY.get(), blockPos, blockState), GenericContainer, MenuProvider {
val energyPerTick: Long = 50
var burningTimeRemaining: Int = 0
@@ -32,6 +32,11 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
override val deviceNode = object : DeviceNode() {
override var powerRole = PowerRole.GENERATOR
override var energyCapacity: Long = 100000
override fun encodeScreenData(player: ServerPlayer, buf: FriendlyByteBuf) {
buf.writeLong(energy)
buf.writeLong(energyCapacity)
}
}
val stacks: NonNullList<ItemStack> = NonNullList<ItemStack>.withSize(1, ItemStack.EMPTY)
@@ -46,8 +51,8 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
return !this.isRemoved
}
override fun tickNode(level: Level) {
super.tickNode(level)
override fun tickDevice(level: Level) {
super.tickDevice(level)
// TODO: give us a block state tag for active
// keep combusting and shi
@@ -79,11 +84,6 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
level?.setBlockAndUpdate(blockPos, blockState.setValue(CombustionGeneratorBlock.COMBUSTGEN_ACTIVE, burningTimeRemaining > 0))
}
override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {
packet.writeLong(deviceNode.energy)
packet.writeLong(deviceNode.energyCapacity)
}
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
super.loadAdditional(compoundTag, provider)
deviceNode.energy = min(deviceNode.energyCapacity, compoundTag.getLong("energy"))

View File

@@ -1,39 +1,67 @@
package org.neoflock.neocomputers.entity;
import net.minecraft.core.BlockPos
import net.minecraft.locale.Language
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
import org.neoflock.neocomputers.network.DeviceNode
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.GPUChar
import org.neoflock.neocomputers.utils.TextBuffer
import kotlin.text.ifEmpty
class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
NodeBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) {
SingleDeviceBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) {
var lastError: String? = null
var isOn: Boolean = false
override val deviceNode = object : DeviceNode() {
override fun received(message: Networking.Message) {
super.received(message)
if(message is Networking.ComputerEvent) {
// return if not directly connected
if(message.sender !in this.connections) return
val mEnv = message.machineEvent
NeoComputers.LOGGER.info("Got message $mEnv!")
if(mEnv is MachinePowerEvent) {
if(mEnv.nowRunning) {
textBuf.set(0, 0, address.toString())
} else {
lastError = null
textBuf.fill(0, 0, textBuf.width, textBuf.height, GPUChar(' '))
textBuf.set(0, 0, address.toString())
}
isOn = mEnv.nowRunning
}
if(mEnv is MachineCrashEvent) {
lastError = mEnv.error
}
}
}
override fun encodeScreenData(player: ServerPlayer, buf: FriendlyByteBuf) {
super.encodeScreenData(player, buf)
textBuf.encodeContents(buf)
}
override fun writeFullStateCommit(buf: FriendlyByteBuf) {
super.writeFullStateCommit(buf)
buf.writeUUID(address)
buf.writeBoolean(isOn)
buf.writeUtf(lastError ?: "")
textBuf.encodeContents(buf)
}
override fun processCommit(buf: FriendlyByteBuf) {
super.processCommit(buf)
if(Networking.changeNodeAddress(this, buf.readUUID())) createscreenstuffs()
isOn = buf.readBoolean()
lastError = buf.readUtf().ifEmpty { null }
textBuf.decodeContents(buf)
}
}
var bound = "screen/unbound"
@@ -41,23 +69,8 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
private var cleanrenderer: () -> Unit = { }; // TODO: THIS SUCKS, FIND A BETTER WAY
override fun encodeDownstreamData(packet: FriendlyByteBuf) {
super.encodeDownstreamData(packet)
textBuf.encodeContents(packet)
}
override fun syncWithUpstream(packet: FriendlyByteBuf) {
super.syncWithUpstream(packet)
textBuf.decodeContents(packet)
}
override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {
super.encodeScreenData(player, packet)
textBuf.encodeContents(packet)
}
override fun tickNode(level: Level) {
super.tickNode(level)
override fun tickDevice(level: Level) {
super.tickDevice(level)
cleanrenderer()
createscreenstuffs()
}
@@ -71,9 +84,29 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
private fun createscreenstuffs() {
bound = "screen/"+deviceNode.address.toString().replace("-", "_")
if (level!!.isClientSide) {
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
renderer.drawBuffer()
cleanrenderer = { renderer.clean() }
if(lastError == null) {
if(!isOn) {
textBuf.fill(0, 0, textBuf.width, textBuf.height)
}
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
renderer.drawBuffer()
cleanrenderer = { renderer.clean() }
} else {
var trueError = lastError!!
if(trueError.startsWith("@")) {
val trans = trueError.substring(1)
val lang = Language.getInstance()
trueError = lang.getOrDefault("neocomputers.computer.errorNoMsg", "Error: ") + lang.getOrDefault(trans)
}
val throwAwayBuf = TextBuffer(50, 16)
val fg = 0xFFFFFF
val bg = 0x2B68A6
throwAwayBuf.fill(0, 0, throwAwayBuf.width, throwAwayBuf.height, GPUChar(' ', fg, bg))
throwAwayBuf.set((throwAwayBuf.width - trueError.length) / 2, throwAwayBuf.height/2, trueError, fg, bg)
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), throwAwayBuf)
renderer.drawBuffer()
cleanrenderer = { renderer.clean() }
}
}
}
}

View File

@@ -1,16 +1,16 @@
package org.neoflock.neocomputers.entity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.core.HolderLookup
import net.minecraft.nbt.CompoundTag
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import org.neoflock.neocomputers.block.NodeBlockEntity
import org.neoflock.neocomputers.block.SingleDeviceBlockEntity
import org.neoflock.neocomputers.network.DeviceNode
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.network.PowerRole
class SolarGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : NodeBlockEntity(BlockEntities.SOLARGEN_ENTITY.get(), blockPos, blockState) {
class SolarGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : SingleDeviceBlockEntity(BlockEntities.SOLARGEN_ENTITY.get(), blockPos, blockState) {
val energyPerTick: Long = 50
override val deviceNode = object : DeviceNode() {
@@ -18,8 +18,8 @@ class SolarGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : No
override var energyCapacity: Long = 50000
}
override fun tickNode(level: Level) {
super.tickNode(level)
override fun tickDevice(level: Level) {
super.tickDevice(level)
val l = level
if(l.isDay) {
deviceNode.giveEnergy(energyPerTick)

View File

@@ -27,6 +27,7 @@ class ScreenEntityRenderer(val context: BlockEntityRendererProvider.Context?) :
.createCompositeState(false))
}
override fun render(entity: ScreenEntity, partialTick: Float, mat: PoseStack, bufferSource: MultiBufferSource, packedLight: Int, packedOverlay: Int) {
if(!entity.isOn && entity.lastError == null) return
val facing = entity.blockState.getValue(ScreenBlock.FACING_HORIZ)
val vert = entity.blockState.getValue(ScreenBlock.FACING_VERTI)-1