This commit is contained in:
mewhenthe
2026-04-21 10:24:51 +02:00
17 changed files with 143 additions and 56 deletions

View File

@@ -0,0 +1,32 @@
package org.neoflock.neocomputers.entity
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import org.neoflock.neocomputers.item.ComponentItem
import org.neoflock.neocomputers.network.Networking
abstract class MachineEvent {
abstract val machine: MachineEntity
}
data class MachineRedstoneEvent(override val machine: MachineEntity, val side: Direction): MachineEvent()
interface MachineEntity {
// Block position of machine, for wireless tech
fun getBlockPosition(): BlockPos
fun isRunning(): Boolean
fun start(): Boolean
fun stop(): Boolean
fun crash(error: String): Boolean
fun getMachineNode(): Networking.Node
// Redstone signals
fun getRedstoneInput(direction: Direction): Int
fun getRedstoneOutput(direction: Direction): Int
// returns the old one
fun setRedstoneOutput(direction: Direction, newValue: Int): Int
}
// TODO: add dummy machine class which implements the machine entity interface meant to be used on the client

View File

@@ -1,5 +1,7 @@
package org.neoflock.neocomputers.gui.menu;
import net.minecraft.core.BlockPos
import net.minecraft.core.Direction
import net.minecraft.world.Container
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
@@ -9,12 +11,36 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.inventory.MenuType
import net.minecraft.world.item.ItemStack
import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.gui.widget.ComponentSlot
import org.neoflock.neocomputers.gui.widget.ComponentSlotRequirement
import org.neoflock.neocomputers.gui.widget.DynamicSlot
import org.neoflock.neocomputers.item.ComponentItem
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.GenericContainerMenu
// lowest IQ machine to exist
class DumbMachine: MachineEntity {
override fun getBlockPosition() = BlockPos.ZERO!!
override fun isRunning() = false
override fun start() = false
override fun stop() = false
override fun crash(error: String) = false
override fun getMachineNode() = Networking.Node()
override fun getRedstoneInput(direction: Direction): Int = 0
override fun getRedstoneOutput(direction: Direction): Int = 0
override fun setRedstoneOutput(direction: Direction, newValue: Int): Int = 0
}
class CaseMenu : GenericContainerMenu {
constructor(i: Int, inv: Inventory) : this(i, inv, SimpleContainer(7))
@@ -28,12 +54,12 @@ class CaseMenu : GenericContainerMenu {
constructor(i: Int, inv: Inventory, container: Container) : super(Menus.CASE_MENU.get(), i, container) {
this.addInventorySlots(inv, 8, 84)
this.addSlot(ComponentSlot(this.container!!, 0, 20, 34, eepromRequirement))
this.addSlot(ComponentSlot(this.container!!, 0, 20, 34, DumbMachine(), eepromRequirement))
var i = 1
for ((col, slotCol) in slotRequirements.withIndex()) {
for ((row, slotReq) in slotCol.withIndex()) {
this.addSlot(ComponentSlot(this.container!!, i, 98+(col*22), 18*(row+1)-2, slotReq))
this.addSlot(ComponentSlot(this.container!!, i, 98+(col*22), 18*(row+1)-2, DumbMachine(), slotReq))
i++
}
}

View File

@@ -10,6 +10,7 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.ItemLike
import org.neoflock.neocomputers.NeoComputers
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.item.ComponentItem
// Sort of a mis-nomer, does not need to be associated with components specifically
@@ -84,7 +85,7 @@ data class ComponentSlotRequirement(val tier: Int, val role: String) {
// Tier 0 allows ALL tiers, making it completely untiered.
// Role determines what the role is.
class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val requirement: ComponentSlotRequirement): DynamicSlot(container, slot, x, y) {
class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val machine: MachineEntity, val requirement: ComponentSlotRequirement): DynamicSlot(container, slot, x, y) {
override fun draw(graphics: GuiGraphics, relX: Int, relY: Int, mouseX: Int, mouseY: Int) {
super.draw(graphics, relX, relY, mouseX, mouseY)
if(!hasItem()) {
@@ -116,14 +117,14 @@ class ComponentSlot(container: Container, slot: Int, x: Int, y: Int, val require
super.set(itemStack)
val item = itemStack.item
if(item is ComponentItem) {
item.whenComponentPlaced(itemStack, requirement.role)
item.whenComponentPlaced(itemStack, machine, requirement.role)
}
}
override fun onTake(player: Player, itemStack: ItemStack) {
val item = itemStack.item
if(item is ComponentItem) {
item.whenComponentTaken(itemStack, requirement.role)
item.whenComponentTaken(itemStack, machine, requirement.role)
}
super.onTake(player, itemStack)
}

View File

@@ -2,6 +2,7 @@ package org.neoflock.neocomputers.item
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
@@ -12,7 +13,7 @@ open class CBUSItem(val tier: Int, val maxComponents: Int): Item(Item.Properties
override fun getComponentCapacity(itemStack: ItemStack): Int = maxComponents
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
}
class CBUS0: CBUSItem(1, 8)
class CBUS1: CBUSItem(2, 12)

View File

@@ -2,6 +2,7 @@ package org.neoflock.neocomputers.item
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
@@ -12,7 +13,7 @@ open class CPUItem(val tier: Int, val maxComponents: Int): Item(Item.Properties(
override fun getComponentCapacity(itemStack: ItemStack): Int = maxComponents
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
}
class CPU0: CPUItem(1, 8)

View File

@@ -1,6 +1,8 @@
package org.neoflock.neocomputers.item
import net.minecraft.world.item.ItemStack
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.entity.MachineEvent
import org.neoflock.neocomputers.network.Networking
import java.util.UUID
@@ -14,19 +16,28 @@ interface ComponentItem {
fun getComponentCapacity(itemStack: ItemStack): Int = 0
// Component placed, node must now exist
fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
val node = toComponentNode(itemStack) ?: return
fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
val oldNode = getComponentNode(itemStack)
if(oldNode != null) Networking.removeNode(oldNode) // did a mod forget to call whenComponentTaken?
val node = toComponentNode(itemStack, machine) ?: return
Networking.addNode(node)
}
// Component taken, and thus removed
fun whenComponentTaken(itemStack: ItemStack, previousRole: String) {
val node = toComponentNode(itemStack) ?: return
fun whenComponentTaken(itemStack: ItemStack, machine: MachineEntity, previousRole: String) {
val node = getComponentNode(itemStack) ?: return
Networking.removeNode(node)
}
// To node, if applicable
fun toComponentNode(itemStack: ItemStack): Networking.Node?
// 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?
// Gets the node associated to an item, if it exists
fun getComponentNode(itemStack: ItemStack): Networking.Node? {
val address = itemStack.get(DataComponents.ADDRESS) ?: return null
val uuid = UUID.fromString(address) ?: return null
return Networking.getNode(uuid)
}
fun ensureHasAddress(itemStack: ItemStack): UUID {
if(!itemStack.has(DataComponents.ADDRESS)) {
@@ -34,4 +45,6 @@ interface ComponentItem {
}
return UUID.fromString(itemStack.get(DataComponents.ADDRESS))
}
fun onMachineEvent(itemStack: ItemStack, machine: MachineEntity, event: MachineEvent) {}
}

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.Formatting
@@ -15,13 +16,13 @@ open class DataCard(val tier: Int, val limit: Long): Item(Properties()), Compone
override fun getComponentTier(itemStack: ItemStack): Int = tier
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
// TODO: Modem Component
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,
@@ -34,7 +35,7 @@ open class DataCard(val tier: Int, val limit: Long): Item(Properties()), Compone
val addrComp = if(addr == null) Component.translatable("neocomputers.noaddr") else Component.literal(addr)
list.addLast(addrComp)
list.addLast(Component.translatable("neocomputers.data.limit", Formatting.formatMemory(limit)))
// TODO: show HTTP/TCP/TLS support
// TODO: show encryption support
}
super.appendHoverText(itemStack, tooltipContext, list, tooltipFlag)
}

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.Formatting
@@ -24,12 +25,12 @@ open class EEPROMItem(val tier: Int, val codeCapacity: Int, val dataCapacity: In
override fun getComponentCapacity(itemStack: ItemStack): Int = 0
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
@@ -14,13 +15,13 @@ open class GPUCard(val tier: Int, val vram: Long): Item(Properties()), Component
override fun getComponentTier(itemStack: ItemStack): Int = tier
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
// TODO: Modem Component
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.Formatting
@@ -22,12 +23,12 @@ open class HardDiskItem(val tier: Int, val capacity: Long): Item(getDiskProperti
override fun getComponentCapacity(itemStack: ItemStack): Int = 0
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.Formatting
@@ -13,13 +14,13 @@ class InternetCard: Item(Item.Properties()), ComponentItem {
override fun getComponentTier(itemStack: ItemStack): Int = 1
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
// TODO: Internet Component
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.Formatting
@@ -17,12 +18,8 @@ open class MemoryItem(val tier: Int, val capacity: Int): Item(Item.Properties().
override fun getComponentCapacity(itemStack: ItemStack): Int = 0
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {}
override fun whenComponentTaken(itemStack: ItemStack, previousRole: String) {}
// no node for memory
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
@@ -12,12 +13,13 @@ open class NetworkCard(val tier: Int, val maxRange: Int, val isWired: Boolean):
override fun getComponentTier(itemStack: ItemStack): Int = tier
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, machine, newRole)
}
// TODO: Modem Component
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
@@ -14,13 +15,13 @@ open class RedstoneCard(val tier: Int): Item(Properties()), ComponentItem {
override fun getComponentTier(itemStack: ItemStack): Int = tier
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
// TODO: Redstone Component
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -4,6 +4,7 @@ import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.TooltipFlag
import org.neoflock.neocomputers.entity.MachineEntity
import org.neoflock.neocomputers.gui.widget.ComponentRoles
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.utils.Formatting
@@ -14,13 +15,13 @@ class TunnelCard: Item(Properties()), ComponentItem {
override fun getComponentTier(itemStack: ItemStack): Int = 3
override fun whenComponentPlaced(itemStack: ItemStack, newRole: String) {
override fun whenComponentPlaced(itemStack: ItemStack, machine: MachineEntity, newRole: String) {
ensureHasAddress(itemStack)
super.whenComponentPlaced(itemStack, newRole)
super.whenComponentPlaced(itemStack, machine, newRole)
}
// TODO: Tunnel Component
override fun toComponentNode(itemStack: ItemStack): Networking.Node? = null
override fun toComponentNode(itemStack: ItemStack, machine: MachineEntity): Networking.Node? = null
override fun appendHoverText(
itemStack: ItemStack,

View File

@@ -44,10 +44,10 @@ object Networking {
class ComputerCheckedSignal(sender: Node, 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)
open class Node {
open class Node(_address: UUID? = null) {
val connections = mutableSetOf<Node>()
private var reachableCache: Set<Node>? = null
open var address = UUID.randomUUID()
var address = _address ?: UUID.randomUUID()
open var reachability = Visibility.NETWORK
open var powerRole = PowerRole.CONSUMER
@@ -237,9 +237,7 @@ object Networking {
}
}
abstract class WirelessEndpoint : Node {
constructor(position: BlockPos);
abstract class WirelessEndpoint(address: UUID?) : Node(address) {
abstract fun getRange(): Double
abstract fun getDimension(): Int
@@ -249,7 +247,7 @@ object Networking {
}
val wirelessNodes = mutableSetOf<WirelessEndpoint>()
val allNodes = mutableSetOf<Node>()
val allNodes = mutableMapOf<UUID, Node>()
// node may differ from message.sender in the case of relays,
// as they might have DIRECT reachability but
@@ -281,18 +279,27 @@ object Networking {
}
fun tickAllNodes() {
allNodes.forEach { it.tick() }
allNodes.forEach { it.value.tick() }
tickCount++
}
fun getNode(address: UUID): Node? = allNodes[address]
// TODO: use setter, more convenient
fun changeNodeAddress(node: Node, address: UUID) {
allNodes.remove(node.address)
node.address = address
allNodes[address] = node
}
fun addNode(node: Node) {
if(node in allNodes) return;
allNodes.add(node)
if(node.address in allNodes) return;
allNodes[node.address] = node
if(node is WirelessEndpoint) {
wirelessNodes.add(node);
}
// notify at the end so it is notified of its own creation
allNodes.forEach { it.onNodeAdded(node) }
allNodes.forEach { it.value.onNodeAdded(node) }
}
fun addNodes(vararg nodes: Node) {
@@ -300,14 +307,14 @@ object Networking {
}
fun removeNode(node: Node) {
if(node !in allNodes) return
allNodes.forEach { it.onNodeRemoved(node) }
if(node.address !in allNodes) return
allNodes.forEach { it.value.onNodeRemoved(node) }
// toList() in order to copy it
node.connections.toList().forEach {
node.disconnectFrom(it)
}
// actually remove at the end so it can listen to its own removal
allNodes.remove(node)
allNodes.remove(node.address)
if(node is WirelessEndpoint) {
wirelessNodes.remove(node);
}

View File

@@ -17,7 +17,7 @@ object PowerManager {
entity, dir -> object : EnergyStorage {
override fun getAmount() = entity.node.energy
override fun getCapacity() = entity.node.energyCapacity
override fun supportsExtraction() = entity.node.powerRole != PowerRole.CONSUMER
override fun supportsExtraction() = entity.node.powerRole != PowerRole.CONSUMER && entity.node.energyCapacity > 0
override fun supportsInsertion() = entity.node.powerRole != PowerRole.GENERATOR
override fun extract(maxAmount: Long, transaction: TransactionContext?): Long {
if(entity.node.powerRole == PowerRole.CONSUMER) return 0