diff --git a/plugins/player_sync/module/player_sync.lua b/plugins/player_sync/module/player_sync.lua index 6d9e7923..1569ae9f 100644 --- a/plugins/player_sync/module/player_sync.lua +++ b/plugins/player_sync/module/player_sync.lua @@ -86,9 +86,6 @@ end -- This function is called internally when a player leaves the game to -- serialize the player for upload. function player_sync.serialize_player(player, player_record) - -- Leaving on the tick of a download, the temporary bonus must not be uploaded - remove_inventory_bonus_raise(get_script_data(), player.name) - -- Editor mode is not supported. if player.controller_type == defines.controllers.editor then player.toggle_map_editor() @@ -116,6 +113,15 @@ function player_sync.serialize_player(player, player_record) local serialized_player = serialize.serialize_player(player, failed_deserialization, player_record.components) serialized_player.generation = player_record.generation + -- Leaving on the tick of a download the temporary bonus is still there and must not be uploaded. Removing it + -- from the character here would shrink the main inventory before the armor's bonus applies and spill items. + local raises = get_script_data().inventory_bonus_raises + local raise = raises and raises[player.name] + local character = serialized_player.character + if raise and character and raise.character == player.character then + character.character_inventory_slots_bonus = character.character_inventory_slots_bonus - raise.bonus + end + return serialized_player end @@ -150,6 +156,8 @@ function player_sync.deserialize_player(player, finished_record) -- Deserialize downloaded player data local serialized_player = compat.json_to_table(finished_record.data) assert(type(serialized_player) == "table", "wrong type for serialized_player") + -- An earlier raise not removed yet is replaced, the character's inventory bonus is restored with the data + script_data.inventory_bonus_raises[player.name] = nil local failed, spill, inventory_bonus_raise = serialize.deserialize_player(player, serialized_player, finished_record.components, local_controller) script_data.failed_deserialization[player.name] = failed @@ -158,7 +166,6 @@ function player_sync.deserialize_player(player, finished_record) script_data.inventory_bonus_raises[player.name] = { character = player.character, bonus = inventory_bonus_raise, - tick = game.tick, } end @@ -419,18 +426,10 @@ player_sync.events[defines.events.on_player_joined_game] = function(event) script_data.active_uploads[player.name] = nil end --- The inventory bonus of armor equipment applies on the tick after a download, the temporary bonus is no longer needed -player_sync.events[defines.events.on_tick] = function(event) - local script_data = get_script_data() - local raises = script_data.inventory_bonus_raises - if not raises or next(raises) == nil then - return - end - for player_name, raise in pairs(raises) do - if raise.tick < event.tick then - remove_inventory_bonus_raise(script_data, player_name) - end - end +-- Raised for a restored armor after its equipment's inventory bonus applied, the temporary bonus is no longer needed +player_sync.events[defines.events.on_player_armor_inventory_changed] = function(event) + local player = assert(game.get_player(event.player_index)) + remove_inventory_bonus_raise(get_script_data(), player.name) end player_sync.on_nth_tick = {} diff --git a/plugins/player_sync/module/serialize.lua b/plugins/player_sync/module/serialize.lua index 10bc518b..fd27b7fa 100644 --- a/plugins/player_sync/module/serialize.lua +++ b/plugins/player_sync/module/serialize.lua @@ -83,7 +83,7 @@ local function last_slot_index(serialized) end --- Raise the inventory bonus of a character with its armor restored to fit a serialized main inventory ---- @return integer raise Slots added to character_inventory_slots_bonus, to be removed again on the next tick +--- @return integer raise Slots added to character_inventory_slots_bonus, removed again once the armor's bonus applies local function raise_inventory_bonus(character, main) local raise = math.max(0, last_slot_index(main) - #character.get_main_inventory()) character.character_inventory_slots_bonus = character.character_inventory_slots_bonus + raise @@ -1386,12 +1386,13 @@ function serialize.deserialize_player(player, serialized, components, local_cont serialize.deserialize_character(character, stats) end local craft = character and queue - -- The bonus of the armor's equipment (toolbelts) only applies on the next tick, so once the armor is - -- restored the main inventory is raised to fit the data + -- The bonus of the armor's equipment (toolbelts) only applies at the end of the tick, so once the armor is + -- restored the main inventory is raised to fit the data. Only for armor with a grid, restoring it raises + -- on_player_armor_inventory_changed which removes the raise. spill = serialize.place_items( serialize.item_destinations(player), inventories, not craft and queue and queue.ingredients or nil, function() - if stats and inventories.main then + if stats and inventories.main and character and character.grid then inventory_bonus_raise = raise_inventory_bonus(character, inventories.main) end end