mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 15:04:52 +09:00
Add script data to allow persistence of unknown recipes
This commit is contained in:
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,
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user