mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 15:14:52 +09:00
Keep the local controller intact when it is not synced
With the controller off, a god or ghost player was still turned into a spectator while downloading, which threw away the local state the sync is meant to leave alone. Only spectate a player without a character when the controller is synced, and skip the ghost round trip when the ghost is the local state. A ghost on an instance that syncs inventories but not the controller never received the stored character, so after respawning it uploaded an empty one over it. Respawn such a ghost straight away when there is a stored character to give it. Clear the saved local controller when the player picks a temporary inventory after a failed download, otherwise a later download restores the stale controller over the temporary character. An empty download only gives a character when the controller is synced or the player was spectated. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0e559cf000
commit
c798b2a33f
5 files changed
+12
-3
No files matched your search
@@ -104,6 +104,7 @@ Defaults to `true`.
|
||||
|
||||
Sync the character and god inventories, the character bonuses and the crafting queue.
|
||||
While the controller is not synced only the inventory of a character is synced, a player without a character keeps the inventory they have on the instance and does not change the stored one.
|
||||
A player waiting to respawn is respawned straight away if there is a synced character to give them.
|
||||
|
||||
Defaults to `true`.
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ local function download_inventory(player_name, data, number, total)
|
||||
progress_dialog.remove(player)
|
||||
|
||||
-- Give the player a character and pretend that's the synced player data
|
||||
if serialize.syncs(script_data.components, "inventories") then
|
||||
if serialize.syncs(script_data.components, "controller") or player_record.local_controller then
|
||||
ensure_character(player)
|
||||
end
|
||||
player_record.local_controller = nil
|
||||
|
||||
@@ -131,6 +131,7 @@ dialog_failed_download.events = {
|
||||
player.gui.screen.dialog_failed_download.destroy()
|
||||
player_sync.players[player.name].dirty = true
|
||||
player_sync.players[player.name].sync = false
|
||||
player_sync.players[player.name].local_controller = nil
|
||||
|
||||
elseif event.element.name == "player_sync_failed_download_retry" then
|
||||
-- Retry acquiring the player from the controller
|
||||
|
||||
@@ -487,7 +487,8 @@ function player_sync.initiate_inventory_download(player, player_record, generati
|
||||
|
||||
-- If this is a synced player turn them into a spectator while the
|
||||
-- player data is downloading
|
||||
if player_record.sync and syncs("inventories") then
|
||||
-- Without the controller synced a player without a character has nothing synced to protect
|
||||
if player_record.sync and syncs("inventories") and (syncs("controller") or player.character) then
|
||||
-- Store original position to teleport back to
|
||||
if v2_remote_controller then
|
||||
record.surface = player.physical_surface
|
||||
|
||||
@@ -987,10 +987,16 @@ function serialize.deserialize_player(player, serialized, components, local_cont
|
||||
local state = local_controller
|
||||
if restore_controller then
|
||||
state = { controller = serialized.controller, ticks_to_respawn = serialized.ticks_to_respawn }
|
||||
elseif state and state.controller == "ghost" and sync_inventories and serialized.character then
|
||||
-- Respawn now, a ghost would drop the synced character and upload an empty one after respawning
|
||||
state = { controller = "character" }
|
||||
end
|
||||
|
||||
local target_controller = state and defines.controllers[state.controller]
|
||||
if state and (player.controller_type ~= target_controller or state.controller == "ghost") then
|
||||
if state and (
|
||||
player.controller_type ~= target_controller
|
||||
or restore_controller and state.controller == "ghost"
|
||||
) then
|
||||
if state.controller == "character" then
|
||||
-- Create a character but do not destroy an existing one
|
||||
ensure_character(player)
|
||||
|
||||
Reference in new issue
Block a user