From 1a1b4fb0d2e967d6bf5c2b73a1a374485efaa235 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 12 Jul 2021 23:28:16 +0200 Subject: [PATCH] Fix invincible ghost character creation on first join Inventory sync will now wait intil the player has a character. This means sync won't happen ex during respawn animations or freeplay intro cutscenes. --- .../inventory_sync/module/inventory_sync.lua | 40 +++++++++++++++---- .../module/upload_inventory.lua | 8 ++-- .../module/welcome_new_player.lua | 4 -- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/plugins/inventory_sync/module/inventory_sync.lua b/plugins/inventory_sync/module/inventory_sync.lua index 915192ce..23c77f1c 100644 --- a/plugins/inventory_sync/module/inventory_sync.lua +++ b/plugins/inventory_sync/module/inventory_sync.lua @@ -2,7 +2,8 @@ When a player leaves the game, serialize their inventory and upload it to the master. -When a player joins the game, send a request to the master server for the players inventory. +When a player joins the game, wait until they have a character, then send a request to +the master server for the players inventory. When the master sends an inventory, parse it and give it to the player. If the master responds that its a new player, show a welcome message. @@ -31,6 +32,7 @@ inventory_sync.events[clusterio_api.events.on_server_startup] = function(event) download_start_tick = {}, saved_crafting_queue = {}, download_cache = {}, + players_waiting_for_download = {}, } end end @@ -47,8 +49,15 @@ end -- Download inventory from master inventory_sync.events[defines.events.on_player_joined_game] = function(event) - local playerIndex = event.player_index - inventory_sync.initiate_inventory_download(playerIndex) + -- Add player to download queue. Inventory won't be downloaded before the player has a character + global.inventory_sync.players_waiting_for_download[game.get_player(event.player_index).name] = true + -- Don't wait for on_nth_tick if not required + inventory_sync.check_player_character_before_download() +end + +inventory_sync.on_nth_tick = {} +inventory_sync.on_nth_tick[33] = function(event) + inventory_sync.check_player_character_before_download() end -- Upload inventory when a player leaves the game. Triggers on restart after crash if player was online during crash. @@ -60,15 +69,30 @@ inventory_sync.events[defines.events.on_pre_player_left_game] = function(event) end local player_index = event.player_index - inventory_sync.upload_inventory(player_index) - global.inventory_sync.download_cache[player_index] = "" -- Clear cache to avoid leaking memory to people quitting during download + local player = game.get_player(player_index) + -- Avoid uploading for unsynced players (due to not having a character, ex during freeplay cutscene) + if global.inventory_sync.players_waiting_for_download[player.name] == nil then + inventory_sync.upload_inventory(player_index) + global.inventory_sync.download_cache[player_index] = "" -- Clear cache to avoid leaking memory to people quitting during download + end + global.inventory_sync.players_waiting_for_download[player.name] = nil end -function inventory_sync.initiate_inventory_download(playerIndex) - local player = game.get_player(playerIndex) +function inventory_sync.check_player_character_before_download() + -- Check if players waiting for download have a valid character + for name in pairs(global.inventory_sync.players_waiting_for_download) do + local player = game.get_player(name) + if player.character ~= nil then + global.inventory_sync.players_waiting_for_download[name] = nil + inventory_sync.initiate_inventory_download(player) + end + end +end + +function inventory_sync.initiate_inventory_download(player) player.print("Initiating inventory download...") global.inventory_sync.download_start_tick[player.name] = game.tick - global.inventory_sync.download_cache[playerIndex] = "" + global.inventory_sync.download_cache[player.name] = "" clusterio_api.send_json("inventory_sync_download", { player_name = player.name }) diff --git a/plugins/inventory_sync/module/upload_inventory.lua b/plugins/inventory_sync/module/upload_inventory.lua index 60476ac9..e6368850 100644 --- a/plugins/inventory_sync/module/upload_inventory.lua +++ b/plugins/inventory_sync/module/upload_inventory.lua @@ -2,14 +2,16 @@ local clusterio_api = require("modules/clusterio/api") local serialize = require("modules/clusterio/serialize") local inventories = require("modules/inventory_sync/define_player_inventories") local save_crafts = require("modules/inventory_sync/save_crafts") -local ensure_character = require("modules/inventory_sync/ensure_character") local player_stat_keys = require("modules/inventory_sync/define_player_stat_keys") function upload_inventory(playerIndex) local player = game.get_player(playerIndex) - -- Force player to have a character to prevent access errors - ensure_character(player) + if player.character == nil then + -- Panic! + log("ERROR: Player "..player.name.." quit without a character. Inventory not uploaded") + return false + end local serialized_player = { name = player.name, diff --git a/plugins/inventory_sync/module/welcome_new_player.lua b/plugins/inventory_sync/module/welcome_new_player.lua index 11090a72..f0d3976f 100644 --- a/plugins/inventory_sync/module/welcome_new_player.lua +++ b/plugins/inventory_sync/module/welcome_new_player.lua @@ -1,13 +1,9 @@ -local ensure_character = require("modules/inventory_sync/ensure_character") - local function welcome_new_player(player_name) local player = game.get_player(player_name) if player == nil then return end player.print("Welcome to the server!") player.print("Your inventory will be automatically synchronized between servers in this cluster.") player.print("To improve sync performance, please avoid storing blueprints in your inventory.") - - ensure_character(player) end return welcome_new_player