reduced network bill by 99.99999% trust
This commit is contained in:
@@ -111,6 +111,19 @@ object NeoComputers {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
NetworkManager.registerReceiver(NetworkManager.c2s(),NodeSynchronizer.DeviceBlockStateRequest.TYPE, NodeSynchronizer.DeviceBlockStateRequest.CODEC, {
|
||||
packet, ctx ->
|
||||
val player = ctx.player
|
||||
val level = player.level()
|
||||
val dist = packet.blockPos.center.distanceTo(player.position())
|
||||
if(player is ServerPlayer && dist <= NodeSynchronizer.MAX_STATE_DISTANCE_ALLOWED) {
|
||||
val ent = level.getBlockEntity(packet.blockPos)
|
||||
if(ent is DeviceBlockEntity) {
|
||||
ent.sendStateToPlayer(player)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// we have to do this because the datagen task runs in the physical server
|
||||
|
||||
@@ -2,10 +2,15 @@ package org.neoflock.neocomputers.block
|
||||
|
||||
import dev.architectury.networking.NetworkManager
|
||||
import io.netty.buffer.Unpooled
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.EntityBlock
|
||||
@@ -27,6 +32,7 @@ abstract class SingleDeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos,
|
||||
abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state: BlockState): BlockEntity(type, pos, state) {
|
||||
val connetionsInDir = MutableList<DeviceNode?>(Direction.entries.size) { null }
|
||||
var alreadySetup = false
|
||||
var receivedServerState = false
|
||||
|
||||
abstract fun getDeviceNodes(): List<DeviceNode>
|
||||
|
||||
@@ -36,6 +42,7 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||
abstract fun getNodeFromSide(directionToRequester: Direction): DeviceNode?
|
||||
|
||||
open fun processCommits(commits: Iterable<FriendlyByteBuf>) {
|
||||
receivedServerState = true
|
||||
val devs = getDeviceNodes()
|
||||
for (buf in commits) {
|
||||
val idx = buf.readVarInt()
|
||||
@@ -89,32 +96,71 @@ abstract class DeviceBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state:
|
||||
}
|
||||
|
||||
open fun sendCommitsToClient(level: Level) {
|
||||
if(level is ServerLevel) {
|
||||
// synchronization!
|
||||
val commits = mutableListOf<FriendlyByteBuf>()
|
||||
val devs = getDeviceNodes()
|
||||
for((i, dev) in devs.withIndex()) {
|
||||
// TODO: use dev.outOfSync to only set commits if something changed, and allow client to request the commits (securely)
|
||||
if(level !is ServerLevel) return
|
||||
// synchronization!
|
||||
val commits = mutableListOf<FriendlyByteBuf>()
|
||||
val devs = getDeviceNodes()
|
||||
for((i, dev) in devs.withIndex()) {
|
||||
if(dev.outOfSync) {
|
||||
dev.outOfSync = false
|
||||
val buf = FriendlyByteBuf(Unpooled.buffer())
|
||||
buf.writeVarInt(i)
|
||||
dev.writeFullStateCommit(buf)
|
||||
commits.addLast(buf)
|
||||
}
|
||||
if(commits.isNotEmpty()) {
|
||||
level.players().forEach {
|
||||
val dist = it.position().distanceTo(blockPos.center)
|
||||
if(dist < 100) NetworkManager.sendToPlayer(it, NodeSynchronizer.DeviceBlockStatePayload(blockPos, commits))
|
||||
}
|
||||
}
|
||||
if(commits.isNotEmpty()) {
|
||||
level.players().forEach {
|
||||
val dist = it.position().distanceTo(blockPos.center)
|
||||
if(dist < 100) NetworkManager.sendToPlayer(it, NodeSynchronizer.DeviceBlockStatePayload(blockPos, commits))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun sendStateToPlayer(player: ServerPlayer) {
|
||||
val world = level!!
|
||||
if(world !is ServerLevel) return
|
||||
// synchronization!
|
||||
val commits = mutableListOf<FriendlyByteBuf>()
|
||||
val devs = getDeviceNodes()
|
||||
for((i, dev) in devs.withIndex()) {
|
||||
val buf = FriendlyByteBuf(Unpooled.buffer())
|
||||
buf.writeVarInt(i)
|
||||
dev.writeFullStateCommit(buf)
|
||||
commits.addLast(buf)
|
||||
}
|
||||
if(commits.isNotEmpty()) {
|
||||
world.players().forEach {
|
||||
val dist = it.position().distanceTo(blockPos.center)
|
||||
if(dist <= NodeSynchronizer.MAX_STATE_DISTANCE_ALLOWED) NetworkManager.sendToPlayer(it, NodeSynchronizer.DeviceBlockStatePayload(blockPos, commits))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun requestServerState() {
|
||||
// no point
|
||||
if(receivedServerState) return
|
||||
// we're the server bro :sob:
|
||||
if(level?.isClientSide != true) return
|
||||
val player = Minecraft.getInstance().player ?: return
|
||||
// we assume the player will just reject, so we save on bandwidth
|
||||
if(player.position().distanceTo(blockPos.center) > NodeSynchronizer.MAX_STATE_DISTANCE_ALLOWED) return
|
||||
NetworkManager.sendToServer(NodeSynchronizer.DeviceBlockStateRequest(blockPos))
|
||||
}
|
||||
|
||||
override fun setRemoved() {
|
||||
super.setRemoved()
|
||||
alreadySetup = false
|
||||
Networking.removeNodes(getDeviceNodes())
|
||||
}
|
||||
|
||||
override fun loadAdditional(tag: CompoundTag, registries: HolderLookup.Provider) {
|
||||
super.loadAdditional(tag, registries)
|
||||
for (node in getDeviceNodes()) {
|
||||
node.markChanged()
|
||||
}
|
||||
receivedServerState = false
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DeviceBlock(properties: Properties = Properties.of()): BaseBlock(properties), EntityBlock {
|
||||
@@ -128,6 +174,9 @@ abstract class DeviceBlock(properties: Properties = Properties.of()): BaseBlock(
|
||||
if(blockEntity !is DeviceBlockEntity) return
|
||||
blockEntity.tickDevice(level)
|
||||
blockEntity.sendCommitsToClient(level)
|
||||
if(level.isClientSide) {
|
||||
blockEntity.requestServerState()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ class CableEntity(pos: BlockPos, state: BlockState) : SingleDeviceBlockEntity(Bl
|
||||
return
|
||||
}
|
||||
|
||||
override fun requestServerState() {
|
||||
// no state, we don't bother
|
||||
return
|
||||
}
|
||||
|
||||
override fun getNodeFromSide(directionToRequester: Direction): DeviceNode? {
|
||||
if(CableBlock.shouldConnect(blockPos, blockPos.relative(directionToRequester), level!!)) {
|
||||
return deviceNode
|
||||
|
||||
@@ -152,6 +152,7 @@ class CaseBlockEntity(blockPos: BlockPos, blockState: BlockState): SingleDeviceB
|
||||
|
||||
fun setRunning(value: Boolean) {
|
||||
if(isOn == value) return
|
||||
deviceNode.markChanged()
|
||||
NeoComputers.LOGGER.info("[${deviceNode.address}] Going from $isOn to $value")
|
||||
isOn = value
|
||||
val world = level ?: return
|
||||
|
||||
@@ -35,9 +35,11 @@ class ScreenEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||
textBuf.set(0, 0, address.toString())
|
||||
}
|
||||
isOn = mEnv.nowRunning
|
||||
markChanged()
|
||||
}
|
||||
if(mEnv is MachineCrashEvent) {
|
||||
lastError = mEnv.error
|
||||
markChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class CaseScreen : GenericContainerScreen<CaseMenu> {
|
||||
if(hasShiftDown()) {
|
||||
msgs.addLast(Component.translatable("neocomputers.computer.energy", energy, maxEnergy).withStyle(if(energy < maxEnergy/5) ChatFormatting.RED else ChatFormatting.WHITE))
|
||||
msgs.addLast(Component.translatable("neocomputers.computer.memory", Formatting.formatMemory(memory), Formatting.formatMemory(maxMemory)))
|
||||
msgs.addLast(Component.translatable("neocomputers.computer.components", components, maxEnergy).withStyle(if(components <= maxComponents) ChatFormatting.WHITE else ChatFormatting.RED))
|
||||
msgs.addLast(Component.translatable("neocomputers.computer.components", components, maxComponents).withStyle(if(components <= maxComponents) ChatFormatting.WHITE else ChatFormatting.RED))
|
||||
}
|
||||
return msgs
|
||||
}
|
||||
|
||||
@@ -51,4 +51,11 @@ interface ComponentItem {
|
||||
}
|
||||
|
||||
fun onMachineEvent(itemStack: ItemStack, machine: MachineEntity, event: MachineEvent) {}
|
||||
}
|
||||
|
||||
// A special ComponentItem which specifies upgrades specific to the relay
|
||||
interface RelayUpgrade: ComponentItem {
|
||||
fun getRelayInterval(itemStack: ItemStack): Int? = null
|
||||
fun getRelayBufferSize(itemStack: ItemStack): Int? = null
|
||||
fun getRelayQueueSize(itemStack: ItemStack): Int? = null
|
||||
}
|
||||
@@ -211,7 +211,7 @@ open class DeviceNode(_address: UUID? = null) {
|
||||
// Network synchronization with the NodeSynchronizer
|
||||
// TODO: process shi
|
||||
|
||||
var outOfSync = true
|
||||
var outOfSync = false
|
||||
fun markChanged() {
|
||||
outOfSync = true
|
||||
}
|
||||
@@ -227,6 +227,12 @@ open class DeviceNode(_address: UUID? = null) {
|
||||
open fun processCommit(buf: FriendlyByteBuf) {}
|
||||
}
|
||||
|
||||
// Used by the relay
|
||||
// If the ComponentItem in the card slot
|
||||
interface ConventionalNetworkDevice {
|
||||
fun sendClassicPacket(packet: Networking.ClassicPacket)
|
||||
}
|
||||
|
||||
abstract class WirelessEndpoint(address: UUID?) : DeviceNode(address) {
|
||||
|
||||
abstract fun getRange(): Double
|
||||
|
||||
@@ -15,10 +15,12 @@ import org.neoflock.neocomputers.NeoComputers
|
||||
import java.time.Duration
|
||||
|
||||
object NodeSynchronizer {
|
||||
val MAX_STATE_DISTANCE_ALLOWED = 128
|
||||
|
||||
class DeviceBlockStatePayload(var blockPos: BlockPos, var buffers: List<FriendlyByteBuf>): CustomPacketPayload {
|
||||
companion object {
|
||||
val NODE_SYNC_ID = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "node_sync")
|
||||
val TYPE = CustomPacketPayload.Type<DeviceBlockStatePayload>(NODE_SYNC_ID)
|
||||
val BLOCKDEV_SYNC_ID = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "blockdev_sync")
|
||||
val TYPE = CustomPacketPayload.Type<DeviceBlockStatePayload>(BLOCKDEV_SYNC_ID)
|
||||
val CODEC = object : StreamCodec<RegistryFriendlyByteBuf, DeviceBlockStatePayload> {
|
||||
override fun decode(buf: RegistryFriendlyByteBuf): DeviceBlockStatePayload {
|
||||
val blockPos = buf.readBlockPos()
|
||||
@@ -45,6 +47,25 @@ object NodeSynchronizer {
|
||||
override fun type() = TYPE
|
||||
}
|
||||
|
||||
class DeviceBlockStateRequest(var blockPos: BlockPos): CustomPacketPayload {
|
||||
companion object {
|
||||
val BLOCKDEV_REQ_ID = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "blockdev_statereq")
|
||||
val TYPE = CustomPacketPayload.Type<DeviceBlockStateRequest>(BLOCKDEV_REQ_ID)
|
||||
val CODEC = object : StreamCodec<RegistryFriendlyByteBuf, DeviceBlockStateRequest> {
|
||||
override fun decode(buf: RegistryFriendlyByteBuf): DeviceBlockStateRequest {
|
||||
val blockPos = buf.readBlockPos()
|
||||
return DeviceBlockStateRequest(blockPos)
|
||||
}
|
||||
|
||||
override fun encode(buf: RegistryFriendlyByteBuf, payload: DeviceBlockStateRequest) {
|
||||
buf.writeBlockPos(payload.blockPos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun type() = TYPE
|
||||
}
|
||||
|
||||
class ScreenPayload(var buffer: FriendlyByteBuf): CustomPacketPayload {
|
||||
companion object {
|
||||
val SCREEN_SYNC_ID = ResourceLocation.fromNamespaceAndPath(NeoComputers.MODID, "screen_sync")
|
||||
|
||||
Reference in New Issue
Block a user