experimental relay bullshit

This commit is contained in:
2026-04-28 20:32:11 +03:00
parent 6ef6826483
commit 3b7e2b02b6
23 changed files with 387 additions and 71 deletions

View File

@@ -34,6 +34,7 @@ object Blocks {
val CASE_BLOCK: RegistrySupplier<Block> = BaseBlock.register("case") { CaseBlock() }
val REDSTONEIO_BLOCK: RegistrySupplier<Block> = BaseBlock.register("redio") { RedstoneIOBlock() }
val CABLE_BLOCK: RegistrySupplier<Block> = BaseBlock.register("cable") { CableBlock() }
val RELAY_BLOCK: RegistrySupplier<Block> = BaseBlock.register("relay") { RelayBlock() }
fun registerBlockItems() {
BLOCKS.forEach(Consumer { sup: RegistrySupplier<Block> ->

View File

@@ -0,0 +1,170 @@
package org.neoflock.neocomputers.block
import dev.architectury.registry.menu.MenuRegistry
import net.minecraft.core.BlockPos
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerLevel
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.ContainerHelper
import net.minecraft.world.InteractionResult
import net.minecraft.world.MenuProvider
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.SoundType
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.BlockHitResult
import org.neoflock.neocomputers.entity.BlockEntities
import org.neoflock.neocomputers.entity.ComponentUser
import org.neoflock.neocomputers.gui.menu.RelayMenu
import org.neoflock.neocomputers.item.RelayUpgrade
import org.neoflock.neocomputers.network.ConventionalNetworkDevice
import org.neoflock.neocomputers.network.DeviceNode
import org.neoflock.neocomputers.network.Networking
import org.neoflock.neocomputers.network.NodeSynchronizer
import org.neoflock.neocomputers.utils.GenericContainer
class RelayEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceBlockEntity(BlockEntities.RELAY_ENTITY.get(), blockPos, blockState),
GenericContainer, ComponentUser, MenuProvider {
companion object RelaySlots {
val CARD = 0
val CPU = 1
val MEM = 2
val STORAGE = 3
val SLOT_COUNT = 4
}
val slots = NonNullList.withSize(SLOT_COUNT, ItemStack.EMPTY)!!
override fun getItems(): NonNullList<ItemStack> = slots
override fun stillValid(player: Player): Boolean = true
fun getUpgrade(slot: Int) = slots[slot].item as? RelayUpgrade
fun computeRelayInterval(): Int = getUpgrade(CPU)?.getRelayInterval(slots[CPU]) ?: 5
fun computeRelayBufferSize(): Int = getUpgrade(MEM)?.getRelayBufferSize(slots[MEM]) ?: 1
fun computeRelayQueueSize(): Int = getUpgrade(STORAGE)?.getRelayQueueSize(slots[STORAGE]) ?: 20
fun getRelaySender(): DeviceNode? = getUpgrade(CARD)?.getComponentNode(slots[CARD])
fun computeRelayCapacity(): Int = computeRelayBufferSize() + computeRelayQueueSize()
val queue = mutableListOf<Networking.ClassicPacket>()
var active = false
var ticksUntilQueue = 0
override val deviceNode = object : DeviceNode() {
override var reachability = Networking.Visibility.NONE
override fun received(message: Networking.Message) {
super.received(message)
if(message.sender == this) return
if(message is Networking.ClassicPacket && message.hopCount <= 5 && queue.size < computeRelayCapacity()) {
queue.addLast(message)
}
}
override fun encodeScreenData(player: ServerPlayer, buf: FriendlyByteBuf) {
super.encodeScreenData(player, buf)
buf.writeVarInt(computeRelayInterval())
buf.writeVarInt(computeRelayBufferSize())
buf.writeVarInt(computeRelayQueueSize())
buf.writeVarInt(queue.size)
}
override fun writeFullStateCommit(buf: FriendlyByteBuf) {
super.writeFullStateCommit(buf)
buf.writeBoolean(active)
}
override fun processCommit(buf: FriendlyByteBuf) {
super.processCommit(buf)
active = buf.readBoolean()
}
}
fun sendQueuedPacket() {
if(queue.isEmpty()) return
val pack = queue.removeFirst()
for(connection in deviceNode.connections) {
// skip unwanted loopback
if(connection !in pack.sender.getReachable()) continue
val hopped = pack.hop(pack.sender)
if(connection is ConventionalNetworkDevice) {
connection.sendClassicPacket(hopped)
} else {
Networking.emitMessage(connection, hopped)
}
}
}
override fun tickDevice(level: Level) {
super.tickDevice(level)
if(level !is ServerLevel) return
ticksUntilQueue--
if(ticksUntilQueue <= 0) {
ticksUntilQueue = computeRelayInterval()
val toSend = computeRelayBufferSize()
for(i in 0..<toSend) {
sendQueuedPacket()
}
}
val cap = computeRelayCapacity()
while(queue.size > cap) queue.removeLast()
active = queue.isNotEmpty()
}
override fun getMachineBlockPosition() = blockPos!!
override fun getMachineLevel() = level!!
override fun getMachineNode() = deviceNode
override fun getDisplayName() = Component.translatable("block.neocomputers.relay")!!
override fun createMenu(
i: Int,
inventory: Inventory,
player: Player
) = RelayMenu(i, inventory, this)
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
super.loadAdditional(tag, registries)
ContainerHelper.loadAllItems(tag, slots, registries)
}
override fun saveAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
super.saveAdditional(tag, registries)
ContainerHelper.saveAllItems(tag, slots, registries)
}
}
class RelayBlock: DeviceBlock(Properties.of().sound(SoundType.METAL)) {
override fun newBlockEntity(pos: BlockPos, state: BlockState) = RelayEntity(pos, state)
override fun useWithoutItem(
state: BlockState,
level: Level,
pos: BlockPos,
player: Player,
hitResult: BlockHitResult
): InteractionResult {
if(!level.isClientSide) {
val ent = level.getBlockEntity(pos, BlockEntities.RELAY_ENTITY.get()).get()
// Open menu
MenuRegistry.openMenu(player as ServerPlayer, ent)
NodeSynchronizer.registerPlayerScreen(player, ent.deviceNode)
}
return InteractionResult.SUCCESS
}
}