From 5071ed3ec1f3ecbc6bf8448057ecd638cd5040f5 Mon Sep 17 00:00:00 2001 From: user01010111 Date: Wed, 29 Jul 2026 17:02:32 +1200 Subject: [PATCH] Fix stale multiplayer state --- scripts/core/RmFreshManager.lua | 21 ++++++++++++++++++++- scripts/events/RmFreshSyncEvent.lua | 10 +++++++++- scripts/events/RmFreshUpdateEvent.lua | 25 ++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/scripts/core/RmFreshManager.lua b/scripts/core/RmFreshManager.lua index ea73c14..8129e49 100644 --- a/scripts/core/RmFreshManager.lua +++ b/scripts/core/RmFreshManager.lua @@ -667,10 +667,29 @@ end --- SERVER ONLY - clients do not call this, they receive events from server ---@param containerId string Container ID ---@param operation number RmFreshUpdateEvent.OP_REGISTER | OP_UPDATE | OP_UNREGISTER ----@param data table|nil Container data (REGISTER), fillUnit data (UPDATE), or nil (UNREGISTER) +---@param data table|nil Container data (REGISTER), changed batch data (UPDATE), or nil (UNREGISTER) function RmFreshManager:broadcastContainerUpdate(containerId, operation, data) if g_server == nil then return end + if operation == RmFreshUpdateEvent.OP_UPDATE then + local container = self.containers[containerId] + if container == nil then + Log:warning("MP_BROADCAST: container not found for update: %s", containerId) + return + end + + local fillTypeName = container.identityMatch + and container.identityMatch.storage + and container.identityMatch.storage.fillTypeName + or "" + + data = { + fillTypeIndex = container.fillTypeIndex, + fillTypeName = fillTypeName, + batches = data and data.batches or container.batches + } + end + g_server:broadcastEvent(RmFreshUpdateEvent.new(containerId, operation, data)) Log:trace("MP_BROADCAST: containerId=%s op=%d", containerId, operation) diff --git a/scripts/events/RmFreshSyncEvent.lua b/scripts/events/RmFreshSyncEvent.lua index 95ca207..8b47d82 100644 --- a/scripts/events/RmFreshSyncEvent.lua +++ b/scripts/events/RmFreshSyncEvent.lua @@ -67,12 +67,15 @@ function RmFreshSyncEvent:writeStream(streamId, connection) -- Write metadata local location = "" local storageClass = RmFreshManager.STORAGE_CLASS.SHELTERED + local isPallet = false if container.metadata then location = container.metadata.location or "" storageClass = container.metadata.storageClass or RmFreshManager.STORAGE_CLASS.SHELTERED + isPallet = container.metadata.isPallet == true end streamWriteString(streamId, location) streamWriteUInt8(streamId, storageClass) + streamWriteBool(streamId, isPallet) -- Write flat batches array (not nested in fillUnits) local batches = container.batches or {} @@ -105,6 +108,8 @@ function RmFreshSyncEvent:writeStream(streamId, connection) streamWriteString(streamId, entry.entityType or "") -- Who (1 int) streamWriteUInt16(streamId, entry.farmId or 0) + -- Storage class (UInt8, 255 = nil/unknown) + streamWriteUInt8(streamId, entry.storageClass or 255) end Log:debug("SYNC_EVENT_WRITE: containers=%d lossLog=%d", containerCount, lossLogCount) @@ -136,6 +141,7 @@ function RmFreshSyncEvent:readStream(streamId, connection) -- Read metadata local location = streamReadString(streamId) local storageClass = streamReadUInt8(streamId) + local isPallet = streamReadBool(streamId) -- Read flat batches local batchCount = streamReadUInt8(streamId) @@ -160,7 +166,7 @@ function RmFreshSyncEvent:readStream(streamId, connection) storage = { fillTypeName = fillTypeName } }, batches = batches, - metadata = { location = location, storageClass = storageClass } + metadata = { location = location, storageClass = storageClass, isPallet = isPallet } } self.containersData[containerId] = container @@ -188,6 +194,8 @@ function RmFreshSyncEvent:readStream(streamId, connection) -- Who farmId = streamReadUInt16(streamId), } + local storageClass = streamReadUInt8(streamId) + entry.storageClass = storageClass ~= 255 and storageClass or nil table.insert(self.lossLog, entry) end diff --git a/scripts/events/RmFreshUpdateEvent.lua b/scripts/events/RmFreshUpdateEvent.lua index 9ee5d32..4f93765 100644 --- a/scripts/events/RmFreshUpdateEvent.lua +++ b/scripts/events/RmFreshUpdateEvent.lua @@ -24,7 +24,7 @@ end --- Constructor with delta data ---@param containerId string Container ID ---@param operation number Operation type (OP_REGISTER, OP_UPDATE, OP_UNREGISTER) ----@param data table|nil Operation data (container for REGISTER, batches for UPDATE, nil for UNREGISTER) +---@param data table|nil Operation data (container for REGISTER, container state for UPDATE, nil for UNREGISTER) function RmFreshUpdateEvent.new(containerId, operation, data) local self = RmFreshUpdateEvent.emptyNew() self.containerId = containerId @@ -68,12 +68,15 @@ function RmFreshUpdateEvent:writeStream(streamId, connection) -- Write metadata local location = "" local storageClass = RmFreshManager.STORAGE_CLASS.SHELTERED + local isPallet = false if container.metadata then location = container.metadata.location or "" storageClass = container.metadata.storageClass or RmFreshManager.STORAGE_CLASS.SHELTERED + isPallet = container.metadata.isPallet == true end streamWriteString(streamId, location) streamWriteUInt8(streamId, storageClass) + streamWriteBool(streamId, isPallet) -- Write flat batches array local batches = container.batches or {} @@ -86,6 +89,10 @@ function RmFreshUpdateEvent:writeStream(streamId, connection) end elseif self.operation == RmFreshUpdateEvent.OP_UPDATE then + -- Write fields that may change while the container remains registered + streamWriteUInt16(streamId, self.data.fillTypeIndex or 0) + streamWriteString(streamId, self.data.fillTypeName or "") + -- Write updated batches array (flat, not per-fillUnit) local batches = self.data.batches or {} local batchCount = #batches @@ -125,6 +132,7 @@ function RmFreshUpdateEvent:readStream(streamId, connection) -- Read metadata local location = streamReadString(streamId) local storageClass = streamReadUInt8(streamId) + local isPallet = streamReadBool(streamId) -- Read flat batches local batchCount = streamReadUInt8(streamId) @@ -149,10 +157,13 @@ function RmFreshUpdateEvent:readStream(streamId, connection) storage = { fillTypeName = fillTypeName } }, batches = batches, - metadata = { location = location, storageClass = storageClass } + metadata = { location = location, storageClass = storageClass, isPallet = isPallet } } elseif self.operation == RmFreshUpdateEvent.OP_UPDATE then + local fillTypeIndex = streamReadUInt16(streamId) + local fillTypeName = streamReadString(streamId) + -- Read updated batches array (flat) local batchCount = streamReadUInt8(streamId) local batches = {} @@ -164,7 +175,11 @@ function RmFreshUpdateEvent:readStream(streamId, connection) }) end - self.data = { batches = batches } + self.data = { + fillTypeIndex = fillTypeIndex, + fillTypeName = fillTypeName, + batches = batches + } elseif self.operation == RmFreshUpdateEvent.OP_UNREGISTER then -- No payload for unregister @@ -204,6 +219,10 @@ function RmFreshUpdateEvent:run(connection) local container = RmFreshManager.containers[self.containerId] if container then container.batches = self.data.batches + container.fillTypeIndex = self.data.fillTypeIndex + if container.identityMatch and container.identityMatch.storage then + container.identityMatch.storage.fillTypeName = self.data.fillTypeName + end Log:debug("UPDATE_EVENT_RUN: UPDATE containerId=%s batches=%d", self.containerId, #self.data.batches) else