clean code, acceptable performance
This commit is contained in:
@@ -4,38 +4,35 @@ import net.minecraft.client.player.LocalPlayer
|
|||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.HolderLookup
|
import net.minecraft.core.HolderLookup
|
||||||
import net.minecraft.nbt.CompoundTag
|
import net.minecraft.nbt.CompoundTag
|
||||||
import net.minecraft.network.chat.ChatType
|
|
||||||
import net.minecraft.network.chat.OutgoingChatMessage
|
import net.minecraft.network.chat.OutgoingChatMessage
|
||||||
import net.minecraft.network.chat.PlayerChatMessage
|
import net.minecraft.network.chat.PlayerChatMessage
|
||||||
import net.minecraft.server.level.ServerPlayer
|
|
||||||
import net.minecraft.world.InteractionResult
|
import net.minecraft.world.InteractionResult
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.item.Item
|
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.phys.BlockHitResult
|
import net.minecraft.world.phys.BlockHitResult
|
||||||
import org.neoflock.neocomputers.entity.BlockEntities
|
import org.neoflock.neocomputers.entity.BlockEntities
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.PowerRole
|
import org.neoflock.neocomputers.network.PowerRole
|
||||||
import kotlin.math.min
|
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) : NodeBlockEntity(type, pos, state) {
|
||||||
|
|
||||||
override val node = object : Networking.Node() {
|
override val deviceNode = object : DeviceNode() {
|
||||||
override var powerRole = PowerRole.STORAGE
|
override var powerRole = PowerRole.STORAGE
|
||||||
override var energyCapacity: Long = capacity
|
override var energyCapacity: Long = capacity
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.loadAdditional(compoundTag, provider)
|
super.loadAdditional(compoundTag, provider)
|
||||||
node.energy = min(compoundTag.getLong("energy"), node.energyCapacity)
|
deviceNode.energy = min(compoundTag.getLong("energy"), deviceNode.energyCapacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.saveAdditional(compoundTag, provider)
|
super.saveAdditional(compoundTag, provider)
|
||||||
compoundTag.putLong("energy", node.energy)
|
compoundTag.putLong("energy", deviceNode.energy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,8 +62,8 @@ class CapacitorBlock(val tier: Int) : NodeBlock() {
|
|||||||
val p = player as LocalPlayer
|
val p = player as LocalPlayer
|
||||||
val ent = level.getBlockEntity(blockPos)
|
val ent = level.getBlockEntity(blockPos)
|
||||||
if(ent is CapacitorEntity) {
|
if(ent is CapacitorEntity) {
|
||||||
if(p.isCrouching) ent.node.giveEnergy(1)
|
if(p.isCrouching) ent.deviceNode.giveEnergy(1)
|
||||||
val msg = PlayerChatMessage.system("energy: ${ent.node.energy} / ${ent.capacity} (${ent.computeEdges().size} edges, ${ent.node.getReachable().size} connected)")
|
val msg = PlayerChatMessage.system("energy: ${ent.deviceNode.energy} / ${ent.capacity} (${ent.computeEdges().size} edges, ${ent.deviceNode.getReachable().size} connected)")
|
||||||
p.sendSystemMessage(OutgoingChatMessage.create(msg).content())
|
p.sendSystemMessage(OutgoingChatMessage.create(msg).content())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType
|
|||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import org.neoflock.neocomputers.NeoComputers
|
import org.neoflock.neocomputers.NeoComputers
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
object NodeSynchronizer {
|
object NodeSynchronizer {
|
||||||
@@ -148,30 +149,30 @@ object NodeSynchronizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState) : BlockEntity(blockEntityType, blockPos, blockState) {
|
abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: BlockPos, blockState: BlockState) : BlockEntity(blockEntityType, blockPos, blockState) {
|
||||||
abstract val node: Networking.Node
|
abstract val deviceNode: DeviceNode
|
||||||
|
|
||||||
fun initNetworking(): NodeBlockEntity {
|
fun initNetworking(): NodeBlockEntity {
|
||||||
Networking.addNode(node)
|
Networking.addNode(deviceNode)
|
||||||
invalidateNodeState()
|
invalidateNodeState()
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
// runs on the server, meant to encode state to send to all players
|
// runs on the server, meant to encode state to send to all players
|
||||||
open fun encodeDownstreamData(packet: FriendlyByteBuf) {
|
open fun encodeDownstreamData(packet: FriendlyByteBuf) {
|
||||||
packet.writeUUID(node.address)
|
packet.writeUUID(deviceNode.address)
|
||||||
packet.writeLong(node.energy)
|
packet.writeLong(deviceNode.energy)
|
||||||
packet.writeLong(node.energyCapacity)
|
packet.writeLong(deviceNode.energyCapacity)
|
||||||
packet.writeEnum(node.reachability)
|
packet.writeEnum(deviceNode.reachability)
|
||||||
packet.writeEnum(node.powerRole)
|
packet.writeEnum(deviceNode.powerRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runs on the client, meant to decode server state packets to synchronize client state
|
// runs on the client, meant to decode server state packets to synchronize client state
|
||||||
open fun syncWithUpstream(packet: FriendlyByteBuf) {
|
open fun syncWithUpstream(packet: FriendlyByteBuf) {
|
||||||
Networking.changeNodeAddress(node, packet.readUUID())
|
Networking.changeNodeAddress(deviceNode, packet.readUUID())
|
||||||
node.energy = packet.readLong()
|
deviceNode.energy = packet.readLong()
|
||||||
node.energyCapacity = packet.readLong()
|
deviceNode.energyCapacity = packet.readLong()
|
||||||
node.reachability = packet.readEnum(node.reachability.javaClass)
|
deviceNode.reachability = packet.readEnum(deviceNode.reachability.javaClass)
|
||||||
node.powerRole = packet.readEnum(node.powerRole.javaClass)
|
deviceNode.powerRole = packet.readEnum(deviceNode.powerRole.javaClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodes data meant for the associated screen of a player
|
// Encodes data meant for the associated screen of a player
|
||||||
@@ -223,7 +224,7 @@ abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: Bl
|
|||||||
if(!stateIsDirty) return
|
if(!stateIsDirty) return
|
||||||
stateIsDirty = false
|
stateIsDirty = false
|
||||||
computeEdges().forEach {
|
computeEdges().forEach {
|
||||||
node.connectTo(it.node)
|
deviceNode.connectTo(it.deviceNode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +236,7 @@ abstract class NodeBlockEntity(blockEntityType: BlockEntityType<*>, blockPos: Bl
|
|||||||
|
|
||||||
override fun setRemoved() {
|
override fun setRemoved() {
|
||||||
super.setRemoved()
|
super.setRemoved()
|
||||||
Networking.removeNode(node)
|
Networking.removeNode(deviceNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearRemoved() {
|
override fun clearRemoved() {
|
||||||
@@ -259,7 +260,7 @@ abstract class NodeBlock(properties: Properties = Properties.of()): BaseBlock(pr
|
|||||||
return object : BlockEntityTicker<T> {
|
return object : BlockEntityTicker<T> {
|
||||||
override fun tick(level: Level, blockPos: BlockPos, blockState: BlockState, blockEntity: T) {
|
override fun tick(level: Level, blockPos: BlockPos, blockState: BlockState, blockEntity: T) {
|
||||||
if(blockEntity !is NodeBlockEntity) return
|
if(blockEntity !is NodeBlockEntity) return
|
||||||
if(Networking.getNode(blockEntity.node.address) == null) blockEntity.initNetworking()
|
if(Networking.getNode(blockEntity.deviceNode.address) == null) blockEntity.initNetworking()
|
||||||
blockEntity.tickNode(level)
|
blockEntity.tickNode(level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ import net.minecraft.world.entity.player.Player
|
|||||||
import net.minecraft.world.level.BlockGetter
|
import net.minecraft.world.level.BlockGetter
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.block.Block
|
import net.minecraft.world.level.block.Block
|
||||||
import net.minecraft.world.level.block.RedStoneWireBlock
|
|
||||||
import net.minecraft.world.level.block.RedstoneTorchBlock
|
|
||||||
import net.minecraft.world.level.block.entity.BlockEntity
|
import net.minecraft.world.level.block.entity.BlockEntity
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.phys.BlockHitResult
|
import net.minecraft.world.phys.BlockHitResult
|
||||||
import org.neoflock.neocomputers.NeoComputers
|
import org.neoflock.neocomputers.NeoComputers
|
||||||
import org.neoflock.neocomputers.entity.BlockEntities
|
import org.neoflock.neocomputers.entity.BlockEntities
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
|
|
||||||
fun dirToIdx(direction: Direction) = Direction.entries.indexOf(direction)
|
fun dirToIdx(direction: Direction) = Direction.entries.indexOf(direction)
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ class RedstoneIOEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnt
|
|||||||
val redstoneOut = Array<Int>(Direction.entries.size) {0}
|
val redstoneOut = Array<Int>(Direction.entries.size) {0}
|
||||||
|
|
||||||
// TODO: have redstone I/O node for component and shi
|
// TODO: have redstone I/O node for component and shi
|
||||||
override val node = object : Networking.Node() {
|
override val deviceNode = object : DeviceNode() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ class RedstoneIOEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnt
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) {
|
fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) {
|
||||||
Networking.emitMessage(node, Networking.ComputerUncheckedSignal(node, "redstone_changed", arrayOf(node.address.toString(), dirToIdx(dir), oldValue, newValue)))
|
Networking.emitMessage(deviceNode, Networking.ComputerUncheckedSignal(deviceNode, "redstone_changed", arrayOf(deviceNode.address.toString(), dirToIdx(dir), oldValue, newValue)))
|
||||||
NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue")
|
NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,32 +7,23 @@ import net.minecraft.core.Direction
|
|||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.chat.Component
|
import net.minecraft.network.chat.Component
|
||||||
import net.minecraft.server.level.ServerPlayer
|
import net.minecraft.server.level.ServerPlayer
|
||||||
import net.minecraft.world.InteractionHand
|
|
||||||
import net.minecraft.world.InteractionResult
|
import net.minecraft.world.InteractionResult
|
||||||
import net.minecraft.world.MenuProvider
|
|
||||||
import net.minecraft.world.entity.LivingEntity
|
|
||||||
import net.minecraft.world.entity.player.Inventory
|
import net.minecraft.world.entity.player.Inventory
|
||||||
import net.minecraft.world.entity.player.Player
|
import net.minecraft.world.entity.player.Player
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||||
import net.minecraft.world.item.ItemStack
|
|
||||||
import net.minecraft.world.item.context.BlockPlaceContext
|
import net.minecraft.world.item.context.BlockPlaceContext
|
||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.block.Block
|
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.BlockEntity
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import net.minecraft.world.level.block.state.StateDefinition
|
import net.minecraft.world.level.block.state.StateDefinition
|
||||||
import net.minecraft.world.level.block.state.properties.BooleanProperty
|
|
||||||
import net.minecraft.world.level.block.state.properties.EnumProperty
|
import net.minecraft.world.level.block.state.properties.EnumProperty
|
||||||
import net.minecraft.world.level.block.state.properties.EnumProperty.*
|
import net.minecraft.world.level.block.state.properties.EnumProperty.*
|
||||||
import net.minecraft.world.level.block.state.properties.IntegerProperty
|
import net.minecraft.world.level.block.state.properties.IntegerProperty
|
||||||
import net.minecraft.world.phys.BlockHitResult
|
import net.minecraft.world.phys.BlockHitResult
|
||||||
import org.neoflock.neocomputers.NeoComputers
|
|
||||||
import org.neoflock.neocomputers.entity.BlockEntities
|
import org.neoflock.neocomputers.entity.BlockEntities
|
||||||
import org.neoflock.neocomputers.entity.ScreenEntity
|
import org.neoflock.neocomputers.entity.ScreenEntity
|
||||||
import org.neoflock.neocomputers.gui.menu.Menus
|
|
||||||
import org.neoflock.neocomputers.gui.menu.ScreenMenu
|
import org.neoflock.neocomputers.gui.menu.ScreenMenu
|
||||||
import org.neoflock.neocomputers.network.Networking
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
@@ -62,7 +53,7 @@ class ScreenBlock() : NodeBlock() {
|
|||||||
): InteractionResult {
|
): InteractionResult {
|
||||||
if(!level.isClientSide) {
|
if(!level.isClientSide) {
|
||||||
val screenState = level.getBlockEntity(blockPos, BlockEntities.SCREEN_ENTITY.get()).get()
|
val screenState = level.getBlockEntity(blockPos, BlockEntities.SCREEN_ENTITY.get()).get()
|
||||||
if(!screenState.node.consumeEnergy(ENERGY)) {
|
if(!screenState.deviceNode.consumeEnergy(ENERGY)) {
|
||||||
player.sendSystemMessage(Component.literal("Not enough power."))
|
player.sendSystemMessage(Component.literal("Not enough power."))
|
||||||
return InteractionResult.SUCCESS
|
return InteractionResult.SUCCESS
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.neoflock.neocomputers.block.NodeSynchronizer
|
|||||||
import org.neoflock.neocomputers.block.dirToIdx
|
import org.neoflock.neocomputers.block.dirToIdx
|
||||||
import org.neoflock.neocomputers.gui.menu.CaseMenu
|
import org.neoflock.neocomputers.gui.menu.CaseMenu
|
||||||
import org.neoflock.neocomputers.item.ComponentItem
|
import org.neoflock.neocomputers.item.ComponentItem
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import org.neoflock.neocomputers.network.PowerRole
|
import org.neoflock.neocomputers.network.PowerRole
|
||||||
import org.neoflock.neocomputers.sounds.ComputerRunningSoundInstance
|
import org.neoflock.neocomputers.sounds.ComputerRunningSoundInstance
|
||||||
@@ -44,7 +45,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
var arch = "Lua 5.3"
|
var arch = "Lua 5.3"
|
||||||
var soundInstance: SoundInstance? = null
|
var soundInstance: SoundInstance? = null
|
||||||
|
|
||||||
override val node = object : Networking.Node() {
|
override val deviceNode = object : DeviceNode() {
|
||||||
override var powerRole = PowerRole.CONSUMER
|
override var powerRole = PowerRole.CONSUMER
|
||||||
override var energyCapacity: Long = 500
|
override var energyCapacity: Long = 500
|
||||||
}
|
}
|
||||||
@@ -79,8 +80,8 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
super.encodeScreenData(player, packet)
|
super.encodeScreenData(player, packet)
|
||||||
packet.writeBoolean(isOn)
|
packet.writeBoolean(isOn)
|
||||||
packet.writeByteArray((err ?: "").encodeToByteArray())
|
packet.writeByteArray((err ?: "").encodeToByteArray())
|
||||||
packet.writeLong(node.energy)
|
packet.writeLong(deviceNode.energy)
|
||||||
packet.writeLong(node.energyCapacity)
|
packet.writeLong(deviceNode.energyCapacity)
|
||||||
packet.writeLong(getMachineMemoryUsed())
|
packet.writeLong(getMachineMemoryUsed())
|
||||||
packet.writeLong(getMachineMemoryTotal())
|
packet.writeLong(getMachineMemoryTotal())
|
||||||
packet.writeLong(getMachineComponentsUsed())
|
packet.writeLong(getMachineComponentsUsed())
|
||||||
@@ -112,12 +113,12 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
item.onMachineEvent(it, this, event)
|
item.onMachineEvent(it, this, event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Networking.emitMessage(node, Networking.ComputerEvent(node, event))
|
Networking.emitMessage(deviceNode, Networking.ComputerEvent(deviceNode, event))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) {
|
fun onRedstoneSignalChanged(dir: Direction, oldValue: Int, newValue: Int) {
|
||||||
sendMachineEvent(MachineRedstoneEvent(this, dir, oldValue, newValue))
|
sendMachineEvent(MachineRedstoneEvent(this, dir, oldValue, newValue))
|
||||||
Networking.emitMessage(node, Networking.ComputerUncheckedSignal(node, "redstone_changed", arrayOf(node.address.toString(), dirToIdx(dir), oldValue, newValue)))
|
Networking.emitMessage(deviceNode, Networking.ComputerUncheckedSignal(deviceNode, "redstone_changed", arrayOf(deviceNode.address.toString(), dirToIdx(dir), oldValue, newValue)))
|
||||||
NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue")
|
NeoComputers.LOGGER.info("redstone in direction ${dir.name} changed from $oldValue to $newValue")
|
||||||
if(oldValue == 0) {
|
if(oldValue == 0) {
|
||||||
// Rising edge
|
// Rising edge
|
||||||
@@ -133,7 +134,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
|
|
||||||
fun setRunning(value: Boolean) {
|
fun setRunning(value: Boolean) {
|
||||||
if(isOn == value) return
|
if(isOn == value) return
|
||||||
NeoComputers.LOGGER.info("[${node.address}] Going from $isOn to $value")
|
NeoComputers.LOGGER.info("[${deviceNode.address}] Going from $isOn to $value")
|
||||||
isOn = value
|
isOn = value
|
||||||
val world = level ?: return
|
val world = level ?: return
|
||||||
blockState?.setValue(CaseBlock.COMPUTER_RUNNING, isOn)
|
blockState?.setValue(CaseBlock.COMPUTER_RUNNING, isOn)
|
||||||
@@ -167,10 +168,10 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
// less than 20% energy is bad
|
// less than 20% energy is bad
|
||||||
if(node.energy < node.energyCapacity/5) {
|
if(deviceNode.energy < deviceNode.energyCapacity/5) {
|
||||||
crash("@neocomputers.errors.ENOENJ")
|
crash("@neocomputers.errors.ENOENJ")
|
||||||
// we add a beep for the special case where we do have a little bit of energy :P
|
// we add a beep for the special case where we do have a little bit of energy :P
|
||||||
if(node.energy > 0) beepAsync("..")
|
if(deviceNode.energy > 0) beepAsync("..")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if(getMachineMemoryTotal() == 0L) {
|
if(getMachineMemoryTotal() == 0L) {
|
||||||
@@ -205,7 +206,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
|
|
||||||
override fun getLastError(): String? = err
|
override fun getLastError(): String? = err
|
||||||
|
|
||||||
override fun getMachineNode(): Networking.Node = node
|
override fun getMachineNode() = deviceNode
|
||||||
|
|
||||||
override fun getRedstoneInput(direction: Direction): Int = redstoneIn[dirToIdx(direction)]
|
override fun getRedstoneInput(direction: Direction): Int = redstoneIn[dirToIdx(direction)]
|
||||||
|
|
||||||
@@ -233,7 +234,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
|
|
||||||
override fun getMachineMemoryTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getMemoryCapacity(it) }.sum().toLong()
|
override fun getMachineMemoryTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getMemoryCapacity(it) }.sum().toLong()
|
||||||
override fun getMachineMemoryUsed(): Long = 0
|
override fun getMachineMemoryUsed(): Long = 0
|
||||||
override fun getMachineComponentsUsed(): Long = node.getReachable().size.toLong()
|
override fun getMachineComponentsUsed(): Long = deviceNode.getReachable().size.toLong()
|
||||||
override fun getMachineComponentsTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getComponentCapacity(it) }.sum().toLong()
|
override fun getMachineComponentsTotal(): Long = stacks.mapNotNull { (it.item as? ComponentItem)?.getComponentCapacity(it) }.sum().toLong()
|
||||||
override fun getMachineArchitecture() = arch
|
override fun getMachineArchitecture() = arch
|
||||||
override fun getMachineArchitectures() = stacks.mapNotNull { (it.item as? ComponentItem)?.getArchitecturesProvided(it) }.flatten().toSet()
|
override fun getMachineArchitectures() = stacks.mapNotNull { (it.item as? ComponentItem)?.getArchitecturesProvided(it) }.flatten().toSet()
|
||||||
@@ -252,14 +253,14 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
|
|
||||||
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.loadAdditional(compoundTag, provider)
|
super.loadAdditional(compoundTag, provider)
|
||||||
node.energy = min(node.energyCapacity, compoundTag.getLong("energy"))
|
deviceNode.energy = min(deviceNode.energyCapacity, compoundTag.getLong("energy"))
|
||||||
//isOn = compoundTag.getBoolean("powerOn")
|
//isOn = compoundTag.getBoolean("powerOn")
|
||||||
ContainerHelper.loadAllItems(compoundTag, getItems(), provider)
|
ContainerHelper.loadAllItems(compoundTag, getItems(), provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.saveAdditional(compoundTag, provider)
|
super.saveAdditional(compoundTag, provider)
|
||||||
compoundTag.putLong("energy", node.energy)
|
compoundTag.putLong("energy", deviceNode.energy)
|
||||||
//compoundTag.putBoolean("powerOn", isOn)
|
//compoundTag.putBoolean("powerOn", isOn)
|
||||||
ContainerHelper.saveAllItems(compoundTag, getItems(), provider)
|
ContainerHelper.saveAllItems(compoundTag, getItems(), provider)
|
||||||
}
|
}
|
||||||
@@ -278,11 +279,12 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): NodeBlockEnti
|
|||||||
if (isRunning()) {
|
if (isRunning()) {
|
||||||
if(diskActivityTime > 0) diskActivityTime--
|
if(diskActivityTime > 0) diskActivityTime--
|
||||||
if(networkActivityTime > 0) networkActivityTime--
|
if(networkActivityTime > 0) networkActivityTime--
|
||||||
if(getMachineComponentsUsed() > getMachineComponentsTotal()) {
|
if(getMachineArchitectures().isEmpty()) {
|
||||||
crash("too many components")
|
crash("@neocomputers.errors.ENOCPU")
|
||||||
}
|
} else if(getMachineComponentsUsed() > getMachineComponentsTotal()) {
|
||||||
if (!node.consumeEnergy(1)) {
|
crash("@neocomputers.errors.E2BIG")
|
||||||
crash("out of energy")
|
} else if (!deviceNode.consumeEnergy(1)) {
|
||||||
|
crash("@neocomputers.errors.ENOENJ")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import net.minecraft.world.level.block.state.BlockState
|
|||||||
import org.neoflock.neocomputers.block.CombustionGeneratorBlock
|
import org.neoflock.neocomputers.block.CombustionGeneratorBlock
|
||||||
import org.neoflock.neocomputers.block.NodeBlockEntity
|
import org.neoflock.neocomputers.block.NodeBlockEntity
|
||||||
import org.neoflock.neocomputers.gui.menu.CombustionGeneratorMenu
|
import org.neoflock.neocomputers.gui.menu.CombustionGeneratorMenu
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import org.neoflock.neocomputers.network.PowerRole
|
import org.neoflock.neocomputers.network.PowerRole
|
||||||
import org.neoflock.neocomputers.utils.GenericContainer
|
import org.neoflock.neocomputers.utils.GenericContainer
|
||||||
@@ -28,7 +29,7 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
|
|
||||||
var burningTimeRemaining: Int = 0
|
var burningTimeRemaining: Int = 0
|
||||||
|
|
||||||
override val node = object : Networking.Node() {
|
override val deviceNode = object : DeviceNode() {
|
||||||
override var powerRole = PowerRole.GENERATOR
|
override var powerRole = PowerRole.GENERATOR
|
||||||
override var energyCapacity: Long = 100000
|
override var energyCapacity: Long = 100000
|
||||||
}
|
}
|
||||||
@@ -52,13 +53,13 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
// keep combusting and shi
|
// keep combusting and shi
|
||||||
if(burningTimeRemaining > 0) {
|
if(burningTimeRemaining > 0) {
|
||||||
burningTimeRemaining--
|
burningTimeRemaining--
|
||||||
node.giveEnergy(energyPerTick)
|
deviceNode.giveEnergy(energyPerTick)
|
||||||
setChanged()
|
setChanged()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// no point
|
// no point
|
||||||
if(node.energy >= node.energyCapacity) return;
|
if(deviceNode.energy >= deviceNode.energyCapacity) return;
|
||||||
|
|
||||||
// :fire:
|
// :fire:
|
||||||
val fuel = stacks[0]
|
val fuel = stacks[0]
|
||||||
@@ -79,20 +80,20 @@ class CombustionGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {
|
override fun encodeScreenData(player: ServerPlayer, packet: FriendlyByteBuf) {
|
||||||
packet.writeLong(node.energy)
|
packet.writeLong(deviceNode.energy)
|
||||||
packet.writeLong(node.energyCapacity)
|
packet.writeLong(deviceNode.energyCapacity)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.loadAdditional(compoundTag, provider)
|
super.loadAdditional(compoundTag, provider)
|
||||||
node.energy = min(node.energyCapacity, compoundTag.getLong("energy"))
|
deviceNode.energy = min(deviceNode.energyCapacity, compoundTag.getLong("energy"))
|
||||||
burningTimeRemaining = compoundTag.getInt("burningTimeRemaining")
|
burningTimeRemaining = compoundTag.getInt("burningTimeRemaining")
|
||||||
ContainerHelper.loadAllItems(compoundTag, getItems(), provider)
|
ContainerHelper.loadAllItems(compoundTag, getItems(), provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.saveAdditional(compoundTag, provider)
|
super.saveAdditional(compoundTag, provider)
|
||||||
compoundTag.putLong("energy", node.energy)
|
compoundTag.putLong("energy", deviceNode.energy)
|
||||||
compoundTag.putInt("burningTimeRemaining", burningTimeRemaining)
|
compoundTag.putInt("burningTimeRemaining", burningTimeRemaining)
|
||||||
ContainerHelper.saveAllItems(compoundTag, getItems(), provider)
|
ContainerHelper.saveAllItems(compoundTag, getItems(), provider)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import net.minecraft.core.Direction
|
|||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.phys.Vec3
|
import net.minecraft.world.phys.Vec3
|
||||||
import org.neoflock.neocomputers.item.ComponentItem
|
import org.neoflock.neocomputers.item.ComponentItem
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ interface MachineEntity {
|
|||||||
fun crash(error: String): Boolean
|
fun crash(error: String): Boolean
|
||||||
fun getLastError(): String?
|
fun getLastError(): String?
|
||||||
|
|
||||||
fun getMachineNode(): Networking.Node
|
fun getMachineNode(): DeviceNode
|
||||||
|
|
||||||
// Some metadata
|
// Some metadata
|
||||||
fun getMachineMemoryTotal(): Long
|
fun getMachineMemoryTotal(): Long
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package org.neoflock.neocomputers.entity;
|
package org.neoflock.neocomputers.entity;
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import net.minecraft.core.HolderLookup
|
|
||||||
import net.minecraft.nbt.CompoundTag
|
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.resources.ResourceLocation
|
import net.minecraft.resources.ResourceLocation
|
||||||
import net.minecraft.server.level.ServerPlayer
|
import net.minecraft.server.level.ServerPlayer
|
||||||
@@ -11,15 +9,15 @@ import net.minecraft.world.level.block.state.BlockState
|
|||||||
import org.neoflock.neocomputers.NeoComputers
|
import org.neoflock.neocomputers.NeoComputers
|
||||||
import org.neoflock.neocomputers.block.NodeBlockEntity
|
import org.neoflock.neocomputers.block.NodeBlockEntity
|
||||||
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
|
import org.neoflock.neocomputers.gui.buffer.BufferRenderer
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import org.neoflock.neocomputers.network.PowerRole
|
|
||||||
import org.neoflock.neocomputers.utils.GPUChar
|
import org.neoflock.neocomputers.utils.GPUChar
|
||||||
import org.neoflock.neocomputers.utils.TextBuffer
|
import org.neoflock.neocomputers.utils.TextBuffer
|
||||||
|
|
||||||
class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
|
class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||||
NodeBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) {
|
NodeBlockEntity(BlockEntities.SCREEN_ENTITY.get(), blockPos, blockState) {
|
||||||
|
|
||||||
override val node = object : Networking.Node() {
|
override val deviceNode = object : DeviceNode() {
|
||||||
override fun received(message: Networking.Message) {
|
override fun received(message: Networking.Message) {
|
||||||
super.received(message)
|
super.received(message)
|
||||||
if(message is Networking.ComputerEvent) {
|
if(message is Networking.ComputerEvent) {
|
||||||
@@ -71,8 +69,7 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createscreenstuffs() {
|
private fun createscreenstuffs() {
|
||||||
bound = "screen/"+node.address.toString().replace("-", "_")
|
bound = "screen/"+deviceNode.address.toString().replace("-", "_")
|
||||||
NeoComputers.LOGGER.info(bound)
|
|
||||||
if (level!!.isClientSide) {
|
if (level!!.isClientSide) {
|
||||||
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
|
var renderer = BufferRenderer(ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, bound), textBuf)
|
||||||
renderer.drawBuffer()
|
renderer.drawBuffer()
|
||||||
|
|||||||
@@ -6,13 +6,14 @@ import net.minecraft.nbt.CompoundTag
|
|||||||
import net.minecraft.world.level.Level
|
import net.minecraft.world.level.Level
|
||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import org.neoflock.neocomputers.block.NodeBlockEntity
|
import org.neoflock.neocomputers.block.NodeBlockEntity
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import org.neoflock.neocomputers.network.PowerRole
|
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) : NodeBlockEntity(BlockEntities.SOLARGEN_ENTITY.get(), blockPos, blockState) {
|
||||||
val energyPerTick: Long = 50
|
val energyPerTick: Long = 50
|
||||||
|
|
||||||
override val node = object : Networking.Node() {
|
override val deviceNode = object : DeviceNode() {
|
||||||
override var powerRole: PowerRole = PowerRole.GENERATOR
|
override var powerRole: PowerRole = PowerRole.GENERATOR
|
||||||
override var energyCapacity: Long = 50000
|
override var energyCapacity: Long = 50000
|
||||||
}
|
}
|
||||||
@@ -21,17 +22,17 @@ class SolarGeneratorBlockEntity(blockPos: BlockPos, blockState: BlockState) : No
|
|||||||
super.tickNode(level)
|
super.tickNode(level)
|
||||||
val l = level
|
val l = level
|
||||||
if(l.isDay) {
|
if(l.isDay) {
|
||||||
node.giveEnergy(energyPerTick)
|
deviceNode.giveEnergy(energyPerTick)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun loadAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.loadAdditional(compoundTag, provider)
|
super.loadAdditional(compoundTag, provider)
|
||||||
node.energy = compoundTag.getLong("energy")
|
deviceNode.energy = compoundTag.getLong("energy")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
override fun saveAdditional(compoundTag: CompoundTag, provider: HolderLookup.Provider) {
|
||||||
super.saveAdditional(compoundTag, provider)
|
super.saveAdditional(compoundTag, provider)
|
||||||
compoundTag.putLong("energy", node.energy)
|
compoundTag.putLong("energy", deviceNode.energy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,13 +7,13 @@ import org.neoflock.neocomputers.gui.widget.ComponentRoles
|
|||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
|
|
||||||
open class CBUSItem(val tier: Int, val maxComponents: Int): Item(Item.Properties()), ComponentItem {
|
open class CBUSItem(val tier: Int, val maxComponents: Int): Item(Item.Properties()), ComponentItem {
|
||||||
override fun getComponentRoles(itemStack: ItemStack): Set<String> = setOf(ComponentRoles.BUS)
|
override fun getComponentRoles(itemStack: ItemStack) = setOf(ComponentRoles.BUS)
|
||||||
|
|
||||||
override fun getComponentTier(itemStack: ItemStack): Int = tier
|
override fun getComponentTier(itemStack: ItemStack) = tier
|
||||||
|
|
||||||
override fun getComponentCapacity(itemStack: ItemStack): Int = maxComponents
|
override fun getComponentCapacity(itemStack: ItemStack) = maxComponents
|
||||||
|
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
}
|
}
|
||||||
class CBUS0: CBUSItem(1, 8)
|
class CBUS0: CBUSItem(1, 8)
|
||||||
class CBUS1: CBUSItem(2, 12)
|
class CBUS1: CBUSItem(2, 12)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ open class CPUItem(val tier: Int, val maxComponents: Int): Item(Item.Properties(
|
|||||||
|
|
||||||
override fun getArchitecturesProvided(itemStack: ItemStack): Set<String> = setOf("Lua 5.3")
|
override fun getArchitecturesProvided(itemStack: ItemStack): Set<String> = setOf("Lua 5.3")
|
||||||
|
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class CPU0: CPUItem(1, 8)
|
class CPU0: CPUItem(1, 8)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.neoflock.neocomputers.item
|
|||||||
import net.minecraft.world.item.ItemStack
|
import net.minecraft.world.item.ItemStack
|
||||||
import org.neoflock.neocomputers.entity.MachineEntity
|
import org.neoflock.neocomputers.entity.MachineEntity
|
||||||
import org.neoflock.neocomputers.entity.MachineEvent
|
import org.neoflock.neocomputers.entity.MachineEvent
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@@ -33,10 +34,10 @@ interface ComponentItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// To node, if applicable. Meant to create the node, but not add it, as it will use the itemStack's address to find it again
|
// To node, if applicable. Meant to create the node, but not add it, as it will use the itemStack's address to find it again
|
||||||
fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node?
|
fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): DeviceNode?
|
||||||
|
|
||||||
// Gets the node associated to an item, if it exists
|
// Gets the node associated to an item, if it exists
|
||||||
fun getComponentNode(itemStack: ItemStack): Networking.Node? {
|
fun getComponentNode(itemStack: ItemStack): DeviceNode? {
|
||||||
val address = itemStack.get(DataComponents.ADDRESS) ?: return null
|
val address = itemStack.get(DataComponents.ADDRESS) ?: return null
|
||||||
val uuid = UUID.fromString(address) ?: return null
|
val uuid = UUID.fromString(address) ?: return null
|
||||||
return Networking.getNode(uuid)
|
return Networking.getNode(uuid)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ open class DataCard(val tier: Int, val limit: Long): Item(Properties()), Compone
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Modem Component
|
// TODO: Modem Component
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ open class EEPROMItem(val tier: Int, val codeCapacity: Int, val dataCapacity: In
|
|||||||
super.whenComponentPlaced(itemStack, machine, newRole)
|
super.whenComponentPlaced(itemStack, machine, newRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ open class GPUCard(val tier: Int, val vram: Long): Item(Properties()), Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: GPU Component
|
// TODO: GPU Component
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ open class HardDiskItem(val tier: Int, val capacity: Long): Item(getDiskProperti
|
|||||||
super.whenComponentPlaced(itemStack, machine, newRole)
|
super.whenComponentPlaced(itemStack, machine, newRole)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class InternetCard: Item(Item.Properties()), ComponentItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Internet Component
|
// TODO: Internet Component
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import net.minecraft.world.item.ItemStack
|
|||||||
import net.minecraft.world.item.TooltipFlag
|
import net.minecraft.world.item.TooltipFlag
|
||||||
import org.neoflock.neocomputers.entity.MachineEntity
|
import org.neoflock.neocomputers.entity.MachineEntity
|
||||||
import org.neoflock.neocomputers.gui.widget.ComponentRoles
|
import org.neoflock.neocomputers.gui.widget.ComponentRoles
|
||||||
|
import org.neoflock.neocomputers.network.DeviceNode
|
||||||
import org.neoflock.neocomputers.network.Networking
|
import org.neoflock.neocomputers.network.Networking
|
||||||
import org.neoflock.neocomputers.utils.Formatting
|
import org.neoflock.neocomputers.utils.Formatting
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ open class MemoryItem(val tier: Int, val capacity: Int): Item(Item.Properties().
|
|||||||
override fun getComponentCapacity(itemStack: ItemStack): Int = 0
|
override fun getComponentCapacity(itemStack: ItemStack): Int = 0
|
||||||
|
|
||||||
// no node for memory
|
// no node for memory
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ open class NetworkCard(val tier: Int, val maxRange: Int, val isWired: Boolean):
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Modem Component
|
// TODO: Modem Component
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ open class RedstoneCard(val tier: Int): Item(Properties()), ComponentItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Redstone Component
|
// TODO: Redstone Component
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ class TunnelCard: Item(Properties().component(DataComponents.TUNNEL_CHANNEL, "cr
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Tunnel Component
|
// TODO: Tunnel Component
|
||||||
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?): Networking.Node? = null
|
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity?) = null
|
||||||
|
|
||||||
override fun appendHoverText(
|
override fun appendHoverText(
|
||||||
itemStack: ItemStack,
|
itemStack: ItemStack,
|
||||||
|
|||||||
235
src/main/kotlin/org/neoflock/neocomputers/network/DeviceNode.kt
Normal file
235
src/main/kotlin/org/neoflock/neocomputers/network/DeviceNode.kt
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
package org.neoflock.neocomputers.network
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos
|
||||||
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
|
import org.neoflock.neocomputers.NeoComputers
|
||||||
|
import org.neoflock.neocomputers.network.Networking.Message
|
||||||
|
import org.neoflock.neocomputers.network.Networking.Visibility
|
||||||
|
import org.neoflock.neocomputers.network.Networking.maxHopCount
|
||||||
|
import java.util.UUID
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
|
open class DeviceNode(_address: UUID? = null) {
|
||||||
|
val connections = HashSet<DeviceNode>()
|
||||||
|
private var reachableCache: Set<DeviceNode>? = null
|
||||||
|
var address = _address ?: UUID.randomUUID()
|
||||||
|
|
||||||
|
open var reachability = Visibility.NETWORK
|
||||||
|
open var powerRole = PowerRole.CONSUMER
|
||||||
|
open var energy: Long = 0
|
||||||
|
open var energyCapacity: Long = 0
|
||||||
|
// give energy, returns how much was actually given
|
||||||
|
// cannot exceed amount specified
|
||||||
|
open fun giveEnergy(amount: Long): Long {
|
||||||
|
val maximum = min(amount, energyCapacity - energy)
|
||||||
|
energy += maximum
|
||||||
|
markChanged()
|
||||||
|
return maximum
|
||||||
|
}
|
||||||
|
// take energy out, returns how much was actually taken
|
||||||
|
// cannot exceed amount specified
|
||||||
|
open fun withdrawEnergy(amount: Long): Long {
|
||||||
|
val maximum = min(amount, energy)
|
||||||
|
energy -= maximum
|
||||||
|
markChanged()
|
||||||
|
return maximum
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getChargerNodes(): Set<DeviceNode> = getReachable().filter { it.powerRole != PowerRole.CONSUMER }.toSet()
|
||||||
|
fun totalEnergyInConnections(): Long = getChargerNodes().fold(0) { acc, node -> acc + node.energy }
|
||||||
|
fun maxEnergyInConnections(): Long = getChargerNodes().fold(0) { acc, node -> acc + node.energyCapacity }
|
||||||
|
|
||||||
|
// attempts to consume
|
||||||
|
fun consumeEnergy(energy: Long): Boolean {
|
||||||
|
// consumes energy, returns false if not enough
|
||||||
|
val total = totalEnergyInConnections() + this.energy
|
||||||
|
if(energy > total) return false
|
||||||
|
|
||||||
|
var remaining = energy
|
||||||
|
remaining -= withdrawEnergy(remaining)
|
||||||
|
if(remaining <= 0) return true
|
||||||
|
|
||||||
|
for (charger in getChargerNodes()) {
|
||||||
|
if(remaining <= 0) break
|
||||||
|
remaining -= charger.withdrawEnergy(remaining)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PLEASE only call if consumer, in the name of all that is holy
|
||||||
|
fun tryToChargeFully() {
|
||||||
|
var remaining = energyCapacity - energy
|
||||||
|
if(remaining <= 0) return
|
||||||
|
for (charger in getChargerNodes()) {
|
||||||
|
if(remaining <= 0) break
|
||||||
|
val amount = charger.withdrawEnergy(remaining)
|
||||||
|
val given = giveEnergy(amount)
|
||||||
|
remaining -= given
|
||||||
|
if(given < amount) {
|
||||||
|
val delta = amount - given // amount lost while given back
|
||||||
|
if(charger.giveEnergy(delta) < delta) {
|
||||||
|
NeoComputers.LOGGER.warn("LOSING ENERGY! Tried giving $delta back to $charger and we're losing our marbles!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only call if storage
|
||||||
|
fun balanceStorage() {
|
||||||
|
for(battery in getReachable()) {
|
||||||
|
if(battery.powerRole != PowerRole.STORAGE) continue
|
||||||
|
// its so if for example we have a battery with 2x the capacity
|
||||||
|
// we don't try to even the energy between them since that's just bad
|
||||||
|
// and might pointless delete energy over time
|
||||||
|
val capacityRatio = energyCapacity.toDouble() / battery.energyCapacity
|
||||||
|
|
||||||
|
val meaningfulSurplus = (battery.energy * capacityRatio - energy).toLong()
|
||||||
|
|
||||||
|
if(meaningfulSurplus <= 0) {
|
||||||
|
// WE'RE greedy (or negligible surplus)? Do nothing
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// steal from this greedy mf
|
||||||
|
val toSteal = meaningfulSurplus / 2
|
||||||
|
if(toSteal == 0L) continue // broke storahh
|
||||||
|
|
||||||
|
val stolen = battery.withdrawEnergy(toSteal)
|
||||||
|
if(giveEnergy(stolen) < stolen) {
|
||||||
|
NeoComputers.LOGGER.warn("LOSING ENERGY IN NODE $address!!!! THIS IS REALLY BAD!!!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rob the generators
|
||||||
|
fun stealGeneratorPower() {
|
||||||
|
var remaining = energyCapacity - energy
|
||||||
|
|
||||||
|
for(generator in getReachable()) {
|
||||||
|
if(generator.powerRole != PowerRole.GENERATOR) continue
|
||||||
|
// rob this mf
|
||||||
|
val robbed = generator.withdrawEnergy(remaining)
|
||||||
|
val taken = giveEnergy(robbed)
|
||||||
|
if(taken < robbed) {
|
||||||
|
NeoComputers.LOGGER.warn("energy caught being DELETED in the big 26")
|
||||||
|
}
|
||||||
|
remaining -= taken
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun tick() {
|
||||||
|
if(powerRole == PowerRole.CONSUMER) tryToChargeFully()
|
||||||
|
if(powerRole == PowerRole.STORAGE) {
|
||||||
|
stealGeneratorPower()
|
||||||
|
balanceStorage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// processes a received message
|
||||||
|
open fun received(message: Message) {}
|
||||||
|
|
||||||
|
// called when a new direct connection is made
|
||||||
|
open fun onConnect(deviceNode: DeviceNode) {}
|
||||||
|
// called when a direct connection is lost
|
||||||
|
open fun onDisconnect(deviceNode: DeviceNode) {}
|
||||||
|
|
||||||
|
// called when a new node is added globally
|
||||||
|
open fun onNodeAdded(deviceNode: DeviceNode) {
|
||||||
|
reachableCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// called when a node is removed globally
|
||||||
|
open fun onNodeRemoved(deviceNode: DeviceNode) {
|
||||||
|
reachableCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getReachable(): Set<DeviceNode> {
|
||||||
|
if(reachableCache == null) {
|
||||||
|
reachableCache = computeReachable();
|
||||||
|
}
|
||||||
|
return reachableCache!!;
|
||||||
|
}
|
||||||
|
|
||||||
|
fun invalidateReachableCache() {
|
||||||
|
reachableCache = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun computeReachable(): Set<DeviceNode> {
|
||||||
|
if(reachability == Visibility.NONE) {
|
||||||
|
return setOf();
|
||||||
|
}
|
||||||
|
if(reachability == Visibility.DIRECT) {
|
||||||
|
return connections.minus(this);
|
||||||
|
}
|
||||||
|
if(reachability == Visibility.NETWORK) {
|
||||||
|
// absolute cinema
|
||||||
|
val working = HashSet<DeviceNode>();
|
||||||
|
val pending = mutableListOf(this);
|
||||||
|
var iterCount = 0;
|
||||||
|
while(iterCount < maxHopCount && pending.isNotEmpty()) {
|
||||||
|
iterCount++;
|
||||||
|
val subnode = pending.removeFirst()
|
||||||
|
if(subnode in working) continue
|
||||||
|
working.add(subnode)
|
||||||
|
if(subnode.reachability == Visibility.NETWORK) {
|
||||||
|
pending.addAll(subnode.connections)
|
||||||
|
} else if(subnode.reachability == Visibility.DIRECT) {
|
||||||
|
working.addAll(subnode.connections)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// cannot send to itself!
|
||||||
|
working.remove(this);
|
||||||
|
return working;
|
||||||
|
}
|
||||||
|
throw NotImplementedError("visibility not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
fun connectTo(other: DeviceNode) {
|
||||||
|
this.directConnectTo(other);
|
||||||
|
other.directConnectTo(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disconnectFrom(other: DeviceNode) {
|
||||||
|
this.directDisconnectFrom(other);
|
||||||
|
other.directDisconnectFrom(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun directConnectTo(other: DeviceNode) {
|
||||||
|
if(other == this) return;
|
||||||
|
if(other in connections) return;
|
||||||
|
connections.add(other);
|
||||||
|
this.onConnect(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
fun directDisconnectFrom(other: DeviceNode) {
|
||||||
|
if(other !in connections) return;
|
||||||
|
connections.remove(other);
|
||||||
|
this.onDisconnect(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Network synchronization with the NodeSynchronizer
|
||||||
|
// TODO: process shi
|
||||||
|
|
||||||
|
var outOfSync = true
|
||||||
|
fun markChanged() {
|
||||||
|
outOfSync = true
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun encodeScreenData(buf: FriendlyByteBuf) {}
|
||||||
|
|
||||||
|
// Meant to write the entire state as a single commit
|
||||||
|
// for clients which say they have no fucking idea what the server is storing
|
||||||
|
open fun writeFullStateCommit(buf: FriendlyByteBuf) {}
|
||||||
|
|
||||||
|
// client-side, meant to bring state forward
|
||||||
|
open fun processCommit(buf: FriendlyByteBuf) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class WirelessEndpoint(address: UUID?) : DeviceNode(address) {
|
||||||
|
|
||||||
|
abstract fun getRange(): Double
|
||||||
|
abstract fun getDimension(): Int
|
||||||
|
abstract fun getPosition(): BlockPos
|
||||||
|
// separate from process for simplicity
|
||||||
|
abstract fun receiveWireless(message: Message, emitter: WirelessEndpoint)
|
||||||
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.neoflock.neocomputers.network
|
package org.neoflock.neocomputers.network
|
||||||
|
|
||||||
import net.minecraft.core.BlockPos
|
import net.minecraft.core.BlockPos
|
||||||
import org.neoflock.neocomputers.NeoComputers
|
|
||||||
import org.neoflock.neocomputers.entity.MachineEvent
|
import org.neoflock.neocomputers.entity.MachineEvent
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
@@ -35,226 +34,24 @@ object Networking {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
abstract class Message(val sender: Node)
|
abstract class Message(val sender: DeviceNode)
|
||||||
|
|
||||||
class ClassicPacket(sender: Node, val src: String, val dst: String, val port: Int, val data: List<Any>, val hopCount: Int) : Message(sender) {
|
class ClassicPacket(sender: DeviceNode, val src: String, val dst: String, val port: Int, val data: List<Any>, val hopCount: Int) : Message(sender) {
|
||||||
fun hop() = ClassicPacket(sender, src, dst, port, data, hopCount + 1);
|
fun hop() = ClassicPacket(sender, src, dst, port, data, hopCount + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for plugins and shi
|
// for plugins and shi
|
||||||
class ComputerCheckedSignal(sender: Node, val player: String?, val name: String, val data: Array<Any>): Message(sender)
|
class ComputerCheckedSignal(sender: DeviceNode, val player: String?, val name: String, val data: Array<Any>): Message(sender)
|
||||||
class ComputerUncheckedSignal(sender: Node, val name: String, val data: Array<Any>): Message(sender)
|
class ComputerUncheckedSignal(sender: DeviceNode, val name: String, val data: Array<Any>): Message(sender)
|
||||||
class ComputerEvent(sender: Node, val machineEvent: MachineEvent): Message(sender)
|
class ComputerEvent(sender: DeviceNode, val machineEvent: MachineEvent): Message(sender)
|
||||||
|
|
||||||
open class Node(_address: UUID? = null) {
|
|
||||||
val connections = mutableSetOf<Node>()
|
|
||||||
private var reachableCache: Set<Node>? = null
|
|
||||||
var address = _address ?: UUID.randomUUID()
|
|
||||||
|
|
||||||
open var reachability = Visibility.NETWORK
|
|
||||||
open var powerRole = PowerRole.CONSUMER
|
|
||||||
open var energy: Long = 0
|
|
||||||
open var energyCapacity: Long = 0
|
|
||||||
// give energy, returns how much was actually given
|
|
||||||
// cannot exceed amount specified
|
|
||||||
open fun giveEnergy(amount: Long): Long {
|
|
||||||
val maximum = min(amount, energyCapacity - energy)
|
|
||||||
energy += maximum
|
|
||||||
return maximum
|
|
||||||
}
|
|
||||||
// take energy out, returns how much was actually taken
|
|
||||||
// cannot exceed amount specified
|
|
||||||
open fun withdrawEnergy(amount: Long): Long {
|
|
||||||
val maximum = min(amount, energy)
|
|
||||||
energy -= maximum
|
|
||||||
return maximum
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getChargerNodes(): Set<Node> = getReachable().filter { it.powerRole != PowerRole.CONSUMER }.toSet()
|
|
||||||
fun totalEnergyInConnections(): Long = getChargerNodes().fold(0) { acc, node -> acc + node.energy }
|
|
||||||
fun maxEnergyInConnections(): Long = getChargerNodes().fold(0) { acc, node -> acc + node.energyCapacity }
|
|
||||||
|
|
||||||
// attempts to consume
|
|
||||||
fun consumeEnergy(energy: Long): Boolean {
|
|
||||||
// consumes energy, returns false if not enough
|
|
||||||
val total = totalEnergyInConnections() + this.energy
|
|
||||||
if(energy > total) return false
|
|
||||||
|
|
||||||
var remaining = energy
|
|
||||||
remaining -= withdrawEnergy(remaining)
|
|
||||||
if(remaining <= 0) return true
|
|
||||||
|
|
||||||
for (charger in getChargerNodes()) {
|
|
||||||
if(remaining <= 0) break
|
|
||||||
remaining -= charger.withdrawEnergy(remaining)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// PLEASE only call if consumer, in the name of all that is holy
|
|
||||||
fun tryToChargeFully() {
|
|
||||||
var remaining = energyCapacity - energy
|
|
||||||
if(remaining <= 0) return
|
|
||||||
for (charger in getChargerNodes()) {
|
|
||||||
if(remaining <= 0) break
|
|
||||||
val amount = charger.withdrawEnergy(remaining)
|
|
||||||
val given = giveEnergy(amount)
|
|
||||||
remaining -= given
|
|
||||||
if(given < amount) {
|
|
||||||
val delta = amount - given // amount lost while given back
|
|
||||||
if(charger.giveEnergy(delta) < delta) {
|
|
||||||
NeoComputers.LOGGER.warn("LOSING ENERGY! Tried giving $delta back to $charger and we're losing our marbles!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// only call if storage
|
|
||||||
fun balanceStorage() {
|
|
||||||
for(battery in getReachable()) {
|
|
||||||
if(battery.powerRole != PowerRole.STORAGE) continue
|
|
||||||
// its so if for example we have a battery with 2x the capacity
|
|
||||||
// we don't try to even the energy between them since that's just bad
|
|
||||||
// and might pointless delete energy over time
|
|
||||||
val capacityRatio = energyCapacity.toDouble() / battery.energyCapacity
|
|
||||||
|
|
||||||
val meaningfulSurplus = (battery.energy * capacityRatio - energy).toLong()
|
|
||||||
|
|
||||||
if(meaningfulSurplus <= 0) {
|
|
||||||
// WE'RE greedy (or negligible surplus)? Do nothing
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// steal from this greedy mf
|
|
||||||
val toSteal = meaningfulSurplus / 2
|
|
||||||
if(toSteal == 0L) continue // broke storahh
|
|
||||||
|
|
||||||
val stolen = battery.withdrawEnergy(toSteal)
|
|
||||||
if(giveEnergy(stolen) < stolen) {
|
|
||||||
NeoComputers.LOGGER.warn("LOSING ENERGY IN NODE $this!!!! THIS IS REALLY BAD!!!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// rob the generators
|
|
||||||
fun stealGeneratorPower() {
|
|
||||||
var remaining = energyCapacity - energy
|
|
||||||
|
|
||||||
for(generator in getReachable()) {
|
|
||||||
if(generator.powerRole != PowerRole.GENERATOR) continue
|
|
||||||
// rob this mf
|
|
||||||
val robbed = generator.withdrawEnergy(remaining)
|
|
||||||
val taken = giveEnergy(robbed)
|
|
||||||
if(taken < robbed) {
|
|
||||||
NeoComputers.LOGGER.warn("energy caught being DELETED in the big 26")
|
|
||||||
}
|
|
||||||
remaining -= taken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun tick() {
|
|
||||||
if(powerRole == PowerRole.CONSUMER) tryToChargeFully()
|
|
||||||
if(powerRole == PowerRole.STORAGE) {
|
|
||||||
stealGeneratorPower()
|
|
||||||
balanceStorage()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// processes a received message
|
|
||||||
open fun received(message: Message) {}
|
|
||||||
|
|
||||||
// called when a new direct connection is made
|
|
||||||
open fun onConnect(node: Node) {}
|
|
||||||
// called when a direct connection is lost
|
|
||||||
open fun onDisconnect(node: Node) {}
|
|
||||||
|
|
||||||
// called when a new node is added globally
|
|
||||||
open fun onNodeAdded(node: Node) {
|
|
||||||
reachableCache = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// called when a node is removed globally
|
|
||||||
open fun onNodeRemoved(node: Node) {
|
|
||||||
reachableCache = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getReachable(): Set<Node> {
|
|
||||||
if(reachableCache == null) {
|
|
||||||
reachableCache = computeReachable();
|
|
||||||
}
|
|
||||||
return reachableCache!!;
|
|
||||||
}
|
|
||||||
|
|
||||||
fun invalidateReachableCache() {
|
|
||||||
reachableCache = null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun computeReachable(): Set<Node> {
|
|
||||||
if(reachability == Visibility.NONE) {
|
|
||||||
return setOf();
|
|
||||||
}
|
|
||||||
if(reachability == Visibility.DIRECT) {
|
|
||||||
return connections.minus(this);
|
|
||||||
}
|
|
||||||
if(reachability == Visibility.NETWORK) {
|
|
||||||
// absolute cinema
|
|
||||||
val working = HashSet<Node>();
|
|
||||||
val pending = mutableListOf(this);
|
|
||||||
var iterCount = 0;
|
|
||||||
while(iterCount < maxHopCount && pending.isNotEmpty()) {
|
|
||||||
iterCount++;
|
|
||||||
val subnode = pending.removeFirst();
|
|
||||||
if(subnode in working) continue;
|
|
||||||
working.add(subnode);
|
|
||||||
pending.addAll(subnode.connections);
|
|
||||||
}
|
|
||||||
// cannot send to itself!
|
|
||||||
working.remove(this);
|
|
||||||
return working;
|
|
||||||
}
|
|
||||||
throw NotImplementedError("visibility not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
fun connectTo(other: Node) {
|
|
||||||
this.directConnectTo(other);
|
|
||||||
other.directConnectTo(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
fun disconnectFrom(other: Node) {
|
|
||||||
this.directDisconnectFrom(other);
|
|
||||||
other.directDisconnectFrom(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
fun directConnectTo(other: Node) {
|
|
||||||
if(other == this) return;
|
|
||||||
if(other in connections) return;
|
|
||||||
connections.add(other);
|
|
||||||
this.onConnect(other);
|
|
||||||
}
|
|
||||||
|
|
||||||
fun directDisconnectFrom(other: Node) {
|
|
||||||
if(other !in connections) return;
|
|
||||||
connections.remove(other);
|
|
||||||
this.onDisconnect(other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class WirelessEndpoint(address: UUID?) : Node(address) {
|
|
||||||
|
|
||||||
abstract fun getRange(): Double
|
|
||||||
abstract fun getDimension(): Int
|
|
||||||
abstract fun getPosition(): BlockPos
|
|
||||||
// separate from process for simplicity
|
|
||||||
abstract fun receiveWireless(message: Message, emitter: WirelessEndpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
val wirelessNodes = ThreadLocal.withInitial { HashSet<WirelessEndpoint>() }
|
val wirelessNodes = ThreadLocal.withInitial { HashSet<WirelessEndpoint>() }
|
||||||
val allNodes = ThreadLocal.withInitial { HashMap<UUID, Node>() }
|
val allNodes = ThreadLocal.withInitial { HashMap<UUID, DeviceNode>() }
|
||||||
|
|
||||||
// node may differ from message.sender in the case of relays,
|
// node may differ from message.sender in the case of relays,
|
||||||
// as they might have DIRECT reachability but
|
// as they might have DIRECT reachability but
|
||||||
fun emitMessage(node: Node, message: Message) {
|
fun emitMessage(deviceNode: DeviceNode, message: Message) {
|
||||||
node.getReachable().forEach { it.received(message) }
|
deviceNode.getReachable().forEach { it.received(message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun computeRangeAllowedByHardness(src: BlockPos, dst: BlockPos): Double {
|
fun computeRangeAllowedByHardness(src: BlockPos, dst: BlockPos): Double {
|
||||||
@@ -285,69 +82,69 @@ object Networking {
|
|||||||
tickCount++
|
tickCount++
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNode(address: UUID): Node? = allNodes.get()[address]
|
fun getNode(address: UUID): DeviceNode? = allNodes.get()[address]
|
||||||
|
|
||||||
// TODO: use setter, more convenient
|
// TODO: use setter, more convenient
|
||||||
fun changeNodeAddress(node: Node, address: UUID) {
|
fun changeNodeAddress(deviceNode: DeviceNode, address: UUID) {
|
||||||
if(node.address.equals(address)) return
|
if(deviceNode.address.equals(address)) return
|
||||||
if(node.address !in allNodes.get()) return
|
if(deviceNode.address !in allNodes.get()) return
|
||||||
allNodes.get().remove(node.address)
|
allNodes.get().remove(deviceNode.address)
|
||||||
node.address = address
|
deviceNode.address = address
|
||||||
allNodes.get()[address] = node
|
allNodes.get()[address] = deviceNode
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addNode(node: Node) {
|
fun addNode(deviceNode: DeviceNode) {
|
||||||
if(node.address in allNodes.get()) return
|
if(deviceNode.address in allNodes.get()) return
|
||||||
allNodes.get()[node.address] = node
|
allNodes.get()[deviceNode.address] = deviceNode
|
||||||
if(node is WirelessEndpoint) {
|
if(deviceNode is WirelessEndpoint) {
|
||||||
wirelessNodes.get().add(node);
|
wirelessNodes.get().add(deviceNode);
|
||||||
}
|
}
|
||||||
// notify at the end so it is notified of its own creation
|
// notify at the end so it is notified of its own creation
|
||||||
allNodes.get().forEach { it.value.onNodeAdded(node) }
|
allNodes.get().forEach { it.value.onNodeAdded(deviceNode) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addNodes(vararg nodes: Node) {
|
fun addNodes(vararg deviceNodes: DeviceNode) {
|
||||||
nodes.forEach { addNode(it) }
|
deviceNodes.forEach { addNode(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeNode(node: Node) {
|
fun removeNode(deviceNode: DeviceNode) {
|
||||||
if(node.address !in allNodes.get()) return
|
if(deviceNode.address !in allNodes.get()) return
|
||||||
allNodes.get().forEach { it.value.onNodeRemoved(node) }
|
allNodes.get().forEach { it.value.onNodeRemoved(deviceNode) }
|
||||||
// toList() in order to copy it
|
// toList() in order to copy it
|
||||||
node.connections.toList().forEach {
|
deviceNode.connections.toList().forEach {
|
||||||
node.disconnectFrom(it)
|
deviceNode.disconnectFrom(it)
|
||||||
}
|
}
|
||||||
// actually remove at the end so it can listen to its own removal
|
// actually remove at the end so it can listen to its own removal
|
||||||
allNodes.get().remove(node.address)
|
allNodes.get().remove(deviceNode.address)
|
||||||
if(node is WirelessEndpoint) {
|
if(deviceNode is WirelessEndpoint) {
|
||||||
wirelessNodes.get().remove(node);
|
wirelessNodes.get().remove(deviceNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeNodes(vararg nodes: Node) {
|
fun removeNodes(vararg deviceNodes: DeviceNode) {
|
||||||
nodes.forEach { removeNode(it) }
|
deviceNodes.forEach { removeNode(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val channels = ThreadLocal.withInitial { HashMap<String, MutableSet<Node>>() }
|
val channels = ThreadLocal.withInitial { HashMap<String, MutableSet<DeviceNode>>() }
|
||||||
|
|
||||||
fun addToChannel(channel: String, node: Node) {
|
fun addToChannel(channel: String, deviceNode: DeviceNode) {
|
||||||
val localChannels = channels.get()
|
val localChannels = channels.get()
|
||||||
if(!localChannels.containsKey(channel)) {
|
if(!localChannels.containsKey(channel)) {
|
||||||
localChannels[channel] = mutableSetOf();
|
localChannels[channel] = mutableSetOf();
|
||||||
}
|
}
|
||||||
localChannels[channel]!!.add(node);
|
localChannels[channel]!!.add(deviceNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeFromChannel(channel: String, node: Node) {
|
fun removeFromChannel(channel: String, deviceNode: DeviceNode) {
|
||||||
val localChannels = channels.get()
|
val localChannels = channels.get()
|
||||||
if(!localChannels.containsKey(channel)) return;
|
if(!localChannels.containsKey(channel)) return;
|
||||||
localChannels[channel]?.remove(node);
|
localChannels[channel]?.remove(deviceNode);
|
||||||
if(localChannels[channel].isNullOrEmpty()) {
|
if(localChannels[channel].isNullOrEmpty()) {
|
||||||
localChannels.remove(channel);
|
localChannels.remove(channel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun emitChannelMessage(starter: Node, channel: String, message: Message) {
|
fun emitChannelMessage(starter: DeviceNode, channel: String, message: Message) {
|
||||||
val localChannels = channels.get()
|
val localChannels = channels.get()
|
||||||
val c = localChannels[channel] ?: return;
|
val c = localChannels[channel] ?: return;
|
||||||
c.forEach { if(it != starter) it.received(message); };
|
c.forEach { if(it != starter) it.received(message); };
|
||||||
|
|||||||
@@ -15,23 +15,23 @@ object PowerManager {
|
|||||||
//? if fabric {
|
//? if fabric {
|
||||||
EnergyStorage.SIDED.registerForBlockEntity({
|
EnergyStorage.SIDED.registerForBlockEntity({
|
||||||
entity, dir -> object : EnergyStorage {
|
entity, dir -> object : EnergyStorage {
|
||||||
override fun getAmount() = entity.node.energy
|
override fun getAmount() = entity.deviceNode.energy
|
||||||
override fun getCapacity() = entity.node.energyCapacity
|
override fun getCapacity() = entity.deviceNode.energyCapacity
|
||||||
override fun supportsExtraction() = entity.node.powerRole != PowerRole.CONSUMER && entity.node.energyCapacity > 0
|
override fun supportsExtraction() = entity.deviceNode.powerRole != PowerRole.CONSUMER && entity.deviceNode.energyCapacity > 0
|
||||||
override fun supportsInsertion() = entity.node.powerRole != PowerRole.GENERATOR
|
override fun supportsInsertion() = entity.deviceNode.powerRole != PowerRole.GENERATOR
|
||||||
override fun extract(maxAmount: Long, transaction: TransactionContext?): Long {
|
override fun extract(maxAmount: Long, transaction: TransactionContext?): Long {
|
||||||
if(entity.node.powerRole == PowerRole.CONSUMER) return 0
|
if(entity.deviceNode.powerRole == PowerRole.CONSUMER) return 0
|
||||||
val taken = entity.node.withdrawEnergy(maxAmount)
|
val taken = entity.deviceNode.withdrawEnergy(maxAmount)
|
||||||
transaction?.addCloseCallback {
|
transaction?.addCloseCallback {
|
||||||
ctx, res -> if(res.wasAborted() || !res.wasCommitted()) entity.node.giveEnergy(taken)
|
ctx, res -> if(res.wasAborted() || !res.wasCommitted()) entity.deviceNode.giveEnergy(taken)
|
||||||
}
|
}
|
||||||
return taken
|
return taken
|
||||||
}
|
}
|
||||||
override fun insert(maxAmount: Long, transaction: TransactionContext?): Long {
|
override fun insert(maxAmount: Long, transaction: TransactionContext?): Long {
|
||||||
if(entity.node.powerRole == PowerRole.GENERATOR) return 0
|
if(entity.deviceNode.powerRole == PowerRole.GENERATOR) return 0
|
||||||
val given = entity.node.giveEnergy(maxAmount)
|
val given = entity.deviceNode.giveEnergy(maxAmount)
|
||||||
transaction?.addCloseCallback { ctx, res ->
|
transaction?.addCloseCallback { ctx, res ->
|
||||||
if (res.wasAborted() || !res.wasCommitted()) entity.node.withdrawEnergy(given)
|
if (res.wasAborted() || !res.wasCommitted()) entity.deviceNode.withdrawEnergy(given)
|
||||||
}
|
}
|
||||||
return given
|
return given
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user