Add script data to allow persistence of unknown recipes

This commit is contained in:
Cooldude2606 committed 2026-03-06 16:05:57 +00:00
1 parent 4badc2e9c1
commit f2833eec33
3 files changed
+33 -8

No files matched your search

@@ -11,6 +11,7 @@ return function(no_early_return)
inventory_sync.players = inventory_sync.players or {}
inventory_sync.players_waiting_for_acquire = inventory_sync.players_waiting_for_acquire or {}
inventory_sync.players_in_cutscene_to_sync = inventory_sync.players_in_cutscene_to_sync or {}
inventory_sync.failed_deserialization = inventory_sync.failed_deserialization or {}
inventory_sync.active_downloads = inventory_sync.active_downloads or {}
inventory_sync.finished_downloads = inventory_sync.finished_downloads or {}
@@ -73,7 +73,8 @@ function inventory_sync.serialize_player(player, player_record)
end
end
local serialized_player = serialize.serialize_player(player)
local failed_deserialization = get_script_data().failed_deserialization[player.name] or {}
local serialized_player = serialize.serialize_player(player, failed_deserialization)
serialized_player.generation = player_record.generation
return serialized_player
@@ -106,7 +107,8 @@ function inventory_sync.deserialize_player(player, finished_record)
-- Deserialize downloaded player data
local serialized_player = compat.json_to_table(finished_record.data)
serialize.deserialize_player(player, serialized_player)
assert(type(serialized_player) == "table", "wrong type for serialized_player")
script_data.failed_deserialization[player.name] = serialize.deserialize_player(player, serialized_player)
-- Restore player position and driving state
restore_position(player, finished_record)
@@ -385,6 +387,7 @@ inventory_sync.events[defines.events.on_pre_player_left_game] = function(event)
player.print("ERROR: Serializing player data failed: " .. result)
return
end
script_data.failed_deserialization[player.name] = nil
script_data.active_uploads[player.name] = {
serialized = result,
last_attempt = game.ticks_played,
+27 -6
View File
@@ -344,8 +344,9 @@ function serialize.deserialize_crafting_queue(player, serialized)
end
---@param player LuaPlayer
---@param failed string[]?
---@return string?
function serialize.serialize_crafting_notifications(player)
function serialize.serialize_crafting_notifications(player, failed)
-- Get all unlocked recipes
local recipes = {}
for _, recipe in pairs(player.force.recipes) do
@@ -360,8 +361,8 @@ function serialize.serialize_crafting_notifications(player)
end
-- Convert to a list of names
local index = 1
local recipe_names = {}
local recipe_names = failed or {} -- Includes previous recipes if any
local index = #recipe_names + 1
for name in pairs(recipes) do
recipe_names[index] = name
index = index + 1
@@ -372,6 +373,7 @@ end
--- @param player LuaPlayer
--- @param serialized string
--- @return string[]? failed Recipe names that do not exist
function serialize.deserialize_crafting_notifications(player, serialized)
-- Decode the recipe name strings
local recipe_names = helpers.json_to_table(assert(helpers.decode_string(serialized)))
@@ -379,6 +381,7 @@ function serialize.deserialize_crafting_notifications(player, serialized)
local clear_notification = player.clear_recipe_notification
local add_notification = player.add_recipe_notification
local notifications = {}
local failed = {}
-- Assume all recipes need a notification
for _, recipe in pairs(player.force.recipes) do
@@ -391,6 +394,9 @@ function serialize.deserialize_crafting_notifications(player, serialized)
for _, recipe_name in pairs(recipe_names) do
if notifications[recipe_name] then
notifications[recipe_name] = false
else
-- Recipe does not exist on this server
failed[#failed+1] = recipe_name
end
end
@@ -408,6 +414,9 @@ function serialize.deserialize_crafting_notifications(player, serialized)
add_notification(recipe_name)
end
end
-- Return failed recipes if any
return next(failed) and failed or nil
end
local controller_to_name = {}
@@ -416,6 +425,7 @@ for name, value in pairs(defines.controllers) do
end
--- @class SerializedPlayerData
--- @field generation number
--- @field name string
--- @field controller string
--- @field color Color
@@ -433,10 +443,12 @@ end
--- @field recipe_notifications string?
--- @param player LuaPlayer
--- @param failed_deserialization FailedDeserializationPlayerData
--- @return SerializedPlayerData
function serialize.serialize_player(player)
function serialize.serialize_player(player, failed_deserialization)
--- @type SerializedPlayerData
local serialized = {
generation = 0, -- Gets replaced later
controller = controller_to_name[player.controller_type],
name = player.name,
color = player.color,
@@ -492,15 +504,21 @@ function serialize.serialize_player(player)
-- Serialize recipe notifications
if recipe_notifications_api then
serialized.recipe_notifications = serialize.serialize_crafting_notifications(player)
serialized.recipe_notifications = serialize.serialize_crafting_notifications(player, failed_deserialization.recipe_notifications)
end
return serialized
end
--- @class FailedDeserializationPlayerData
--- @field recipe_notifications string[]?
--- @param player LuaPlayer
--- @param serialized SerializedPlayerData
--- @return FailedDeserializationPlayerData?
function serialize.deserialize_player(player, serialized)
local failed_deserialization = {}
if player.controller_type ~= defines.controllers[serialized.controller] or serialized.controller == "ghost" then
-- If targeting the character or ghost controller then create a character
if serialized.controller == "character" or serialized.controller == "ghost" then
@@ -582,8 +600,11 @@ function serialize.deserialize_player(player, serialized)
-- Deserialize recipe notifications
if recipe_notifications_api and serialized.recipe_notifications then
serialize.deserialize_crafting_notifications(player, serialized.recipe_notifications)
failed_deserialization.recipe_notifications =
serialize.deserialize_crafting_notifications(player, serialized.recipe_notifications)
end
return next(failed_deserialization) and failed_deserialization or nil
end
return serialize