mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
The scenario no longer sends its components with the download request. The instance strips the download by its own config and sends the components it used with the first chunk. If they differ from the ones the scenario started the download with, because the config changed in between, the scenario restarts the download. A pending download is now marked with sync_in_progress instead of clearing dirty while spectating, and it is set for every download rather than only when inventories are synced. Uploads are skipped while it is set, so a player who leaves during a download with inventories off no longer uploads their stale state. SyncComponent names the components in the Lua annotations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
91 lines
3.1 KiB
Lua
91 lines
3.1 KiB
Lua
local progress_dialog = require("modules/player_sync/gui/progress_dialog")
|
|
local ensure_character = require("modules/player_sync/ensure_character")
|
|
local restore_position = require("modules/player_sync/restore_position")
|
|
local get_script_data = require("modules/player_sync/get_script_data")
|
|
local serialize = require("modules/player_sync/serialize")
|
|
local compat = require("modules/clusterio/compat")
|
|
|
|
|
|
--- @param components string? JSON of the components the instance sent the data with, given with the first part
|
|
local function download_inventory(player_name, data, number, total, components)
|
|
local player = game.get_player(player_name)
|
|
if player == nil then
|
|
rcon.print("Player " .. player_name .. " does not exist")
|
|
return
|
|
end
|
|
|
|
local script_data = get_script_data()
|
|
local record = script_data.active_downloads[player_name]
|
|
if record == nil then
|
|
rcon.print("No active download is in progress for " .. player_name)
|
|
return
|
|
end
|
|
|
|
local player_record = script_data.players[player_name]
|
|
-- The components changed after the download was started
|
|
local sent_components = number == 1 and components and compat.json_to_table(components)
|
|
if sent_components and not serialize.same_components(record.components, sent_components) then
|
|
record.restart = true
|
|
end
|
|
if record.restart then
|
|
rcon.print("Restarting outdated download")
|
|
player_sync.initiate_inventory_download(player, player_record, record.generation)
|
|
return
|
|
end
|
|
|
|
if total == 0 then
|
|
-- Download was requested but the player had no data stored.
|
|
log("ERROR: Player sync failed, got empty player data for " .. player.name .. " from the controller")
|
|
player.print("ERROR: Player sync failed, got empty player data from the controller")
|
|
|
|
progress_dialog.remove(player)
|
|
|
|
-- Give the player a character and pretend that's the synced player data
|
|
if serialize.syncs(record.components, "controller") or player_record.local_controller then
|
|
ensure_character(player)
|
|
end
|
|
player_record.local_controller = nil
|
|
|
|
-- Restore player position and driving state
|
|
restore_position(player, record)
|
|
|
|
script_data.active_downloads[player_name] = nil
|
|
player_record.dirty = player.connected
|
|
player_record.sync_in_progress = false
|
|
player_record.sync = true
|
|
player_record.components = record.components
|
|
player_record.generation = record.generation
|
|
return
|
|
end
|
|
|
|
record.data = record.data .. data
|
|
|
|
-- Show progress in console
|
|
-- player.print("Downloaded "..(number + 1).."/"..total.." parts")
|
|
if number ~= total then
|
|
-- Show progress in GUI
|
|
progress_dialog.display(player, number, total)
|
|
|
|
-- Update activity to indicate this session is still going
|
|
record.last_active = game.ticks_played
|
|
return
|
|
end
|
|
|
|
-- Download is complete
|
|
progress_dialog.remove(player)
|
|
|
|
-- Remove download session and store finished download
|
|
script_data.active_downloads[player_name] = nil
|
|
script_data.finished_downloads[player_name] = record
|
|
|
|
local ticks = game.ticks_played - record.started
|
|
player.print("Imported player data in " .. ticks .. " ticks")
|
|
log("Imported player data for " .. player_name .. " in " .. ticks .. " ticks")
|
|
|
|
if player.connected then
|
|
player_sync.finish_download(player, record)
|
|
end
|
|
end
|
|
|
|
return download_inventory
|