From 254c43c08140ed9cce63b2a522eeb875d358dc23 Mon Sep 17 00:00:00 2001 From: Piratux <58703216+Piratux@users.noreply.github.com> Date: Mon, 26 Jun 2023 21:51:55 +0300 Subject: [PATCH] Player leaving/joining changes Changes: - Fixed an issue where player force wasn't properly set to default force, when player joined the game 2nd time after 5 minutes, which caused all sorts of issues (such as being able to take classes while staying in lobby, etc.) - Player inventory when player leaves the crew (either to lobby or quite game) now remains in their character corpse. - When player leaves and joins the game within 1 minute, he will spawn where he left. --- maps/pirates/api_events.lua | 21 ++++++--- maps/pirates/api_on_tick.lua | 48 ++++++++++---------- maps/pirates/common.lua | 6 ++- maps/pirates/crew.lua | 87 ++++++++++++++++++++---------------- maps/pirates/gui/crew.lua | 2 +- maps/pirates/gui/runs.lua | 17 ++++--- maps/pirates/memory.lua | 5 +-- 7 files changed, 106 insertions(+), 80 deletions(-) diff --git a/maps/pirates/api_events.lua b/maps/pirates/api_events.lua index fd9c8e08..5f164884 100644 --- a/maps/pirates/api_events.lua +++ b/maps/pirates/api_events.lua @@ -1437,22 +1437,26 @@ local function event_on_player_joined_game(event) local crew_to_put_back_in = nil for _, memory in pairs(global_memory.crew_memories) do - if Common.is_id_valid(memory.id) and memory.crewstatus == Crew.enum.ADVENTURING and memory.temporarily_logged_off_characters[player.index] then + if Common.is_id_valid(memory.id) and memory.crewstatus == Crew.enum.ADVENTURING and memory.temporarily_logged_off_player_data[player.index] then crew_to_put_back_in = memory.id break end end if crew_to_put_back_in then - Crew.join_crew(player, crew_to_put_back_in, true) + log('INFO: ' .. player.name .. ' (crew ID: ' .. crew_to_put_back_in .. ') joined the game') - local memory = global_memory.crew_memories[crew_to_put_back_in] + Memory.set_working_id(crew_to_put_back_in) + Crew.join_crew(player, true) + + local memory = Memory.get_crew_memory() if (not memory.run_is_protected) and #memory.crewplayerindices <= 1 then Roles.make_captain(player) end if _DEBUG then log('putting player back in their old crew') end else + log('INFO: ' .. player.name .. ' (crew ID: NONE) joined the game') if player.character and player.character.valid then player.character.destroy() end @@ -1475,6 +1479,8 @@ local function event_on_player_joined_game(event) Common.notify_player_expected(player, {'pirates.player_join_game_info'}) + player.force = Common.lobby_force_name + -- It was suggested to always spawn players in lobby, in hopes that they may want to create their crew increasing the popularity of scenario. -- Auto-join the oldest crew: @@ -1505,7 +1511,7 @@ local function event_on_player_joined_game(event) -- end -- ) -- if ages[1] then - -- Crew.join_crew(player, ages[1].id) + -- Crew.join_crew(player) -- local memory = global_memory.crew_memories[ages[1].id] -- if (not memory.run_is_protected) and #memory.crewplayerindices <= 1 then @@ -1565,6 +1571,11 @@ local function event_on_pre_player_left_game(event) local global_memory = Memory.get_global_memory() -- figure out which crew this is about: local crew_id = Common.get_id_from_force_name(player.force.name) + if crew_id then + log('INFO: ' .. player.name .. ' (crew ID: ' .. crew_id .. ') left the game') + else + log('INFO: ' .. player.name .. ' (crew ID: NONE) left the game') + end for k, proposal in pairs(global_memory.crewproposals) do if proposal and proposal.endorserindices then @@ -2082,7 +2093,7 @@ local function event_on_console_chat(event) local memory = Memory.get_crew_memory() -- NOTE: This check to see if player is in a crew is not reliable and can sometimes cause errors! - if player.force.name == 'player' then + if player.force.name == Common.lobby_force_name then local other_force_indices = global_memory.crew_active_ids for _, index in pairs(other_force_indices) do diff --git a/maps/pirates/api_on_tick.lua b/maps/pirates/api_on_tick.lua index dec472df..79f02d28 100644 --- a/maps/pirates/api_on_tick.lua +++ b/maps/pirates/api_on_tick.lua @@ -262,34 +262,34 @@ function Public.prune_offline_characters_list(tickinterval) if memory.game_lost then return end - for player_index, tick in pairs(memory.temporarily_logged_off_characters) do - if player_index and game.players[player_index] and game.players[player_index].connected then - memory.temporarily_logged_off_characters[player_index] = nil - if memory.temporarily_logged_off_characters_items[player_index] then - memory.temporarily_logged_off_characters_items[player_index].destroy() - end - memory.temporarily_logged_off_characters_items[player_index] = nil + for player_index, data in pairs(memory.temporarily_logged_off_player_data) do + if game.players[player_index] and game.players[player_index].connected then + -- memory.temporarily_logged_off_characters[player_index] = nil + -- if memory.temporarily_logged_off_characters_items[player_index] then + -- memory.temporarily_logged_off_characters_items[player_index].destroy() + -- end + -- memory.temporarily_logged_off_characters_items[player_index] = nil memory.temporarily_logged_off_player_data[player_index] = nil else - if player_index and tick < game.tick - 60 * 60 * Common.logged_off_items_preserved_minutes then - local any = false - local temp_inv = memory.temporarily_logged_off_characters_items[player_index] - if temp_inv then - for i = 1, #temp_inv, 1 do - if temp_inv[i] and temp_inv[i].valid and temp_inv[i].valid_for_read then - Common.give_items_to_crew(temp_inv[i]) - any = true - end - end - if any then - Common.notify_force_light(memory.force, {'pirates.recover_offline_player_items'}) - end + local tick = data.tick + if tick < game.tick - 60 * 60 * Common.temporarily_logged_off_player_data_preservation_minutes then + -- local any = false + -- local temp_inv = memory.temporarily_logged_off_characters_items[player_index] + -- if temp_inv then + -- for i = 1, #temp_inv, 1 do + -- if temp_inv[i] and temp_inv[i].valid and temp_inv[i].valid_for_read then + -- Common.give_items_to_crew(temp_inv[i]) + -- any = true + -- end + -- end - temp_inv.destroy() - end + -- if any then + -- Common.notify_force_light(memory.force, {'pirates.recover_offline_player_items'}) + -- end + + -- temp_inv.destroy() + -- end - memory.temporarily_logged_off_characters[player_index] = nil - memory.temporarily_logged_off_characters_items[player_index] = nil memory.temporarily_logged_off_player_data[player_index] = nil end end diff --git a/maps/pirates/common.lua b/maps/pirates/common.lua index edec14ba..3cc9f25e 100644 --- a/maps/pirates/common.lua +++ b/maps/pirates/common.lua @@ -63,9 +63,11 @@ Public.ban_from_rejoining_crew_ticks = 45 * 60 --to prevent observing map and re Public.afk_time = 60 * 60 * 5 Public.afk_warning_time = 60 * 60 * 4.5 -Public.logged_off_items_preserved_minutes = 1 +Public.temporarily_logged_off_player_data_preservation_minutes = 1 Public.logout_unprotected_items = {'uranium-235', 'uranium-238', 'fluid-wagon', 'coal', 'electric-engine-unit', 'flying-robot-frame', 'advanced-circuit', 'beacon', 'speed-module-3', 'speed-module-2', 'roboport', 'construction-robot'} --internal inventories of these will not be preserved +Public.lobby_force_name = 'player' + -- Public.mainshop_rate_limit_ticks = 11 @@ -138,7 +140,7 @@ end function Public.notify_lobby(message, color_override) color_override = color_override or CoreData.colors.notify_lobby - game.forces['player'].print({"", '>> ', message}, color_override) + game.forces[Public.lobby_force_name].print({"", '>> ', message}, color_override) end function Public.notify_force(force, message, color_override) diff --git a/maps/pirates/crew.lua b/maps/pirates/crew.lua index 7e6c2491..f7b6eb74 100644 --- a/maps/pirates/crew.lua +++ b/maps/pirates/crew.lua @@ -268,7 +268,7 @@ function Public.join_spectators(player, crewid) player.set_controller{type = defines.controllers.spectator} end - local c = surface.create_entity{name = 'character', position = surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, force = 'player'} + local c = surface.create_entity{name = 'character', position = surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, force = Common.lobby_force_name} player.associate_character(c) @@ -333,14 +333,11 @@ function Public.leave_spectators(player, quiet) if _DEBUG then memory.crew_disband_tick = game.tick + 30*60*60 end end - player.force = 'player' + player.force = Common.lobby_force_name end -function Public.join_crew(player, crewid, rejoin) - if not crewid then return end - - Memory.set_working_id(crewid) +function Public.join_crew(player, rejoin) local memory = Memory.get_crew_memory() if not Common.validate_player(player) then return end @@ -369,7 +366,7 @@ function Public.join_crew(player, crewid, rejoin) if spectating then local chars = player.get_associated_characters() for _, char in pairs(chars) do - char.destroy() + char.destroy() end player.teleport(surface.find_non_colliding_position('character', memory.spawnpoint, 32, 0.5) or memory.spawnpoint, surface) @@ -379,6 +376,11 @@ function Public.join_crew(player, crewid, rejoin) memory.spectatorplayerindices = Utils.ordered_table_with_values_removed(memory.spectatorplayerindices, player.index) else + if not (player.character and player.character.valid) then + player.set_controller{type = defines.controllers.god} + player.create_character() + end + Public.player_abandon_endorsements(player) player.force = memory.force @@ -394,16 +396,17 @@ function Public.join_crew(player, crewid, rejoin) -- If surface where player left the game still exists, place him there. if rejoin_surface and rejoin_surface.valid then -- Edge case: if player left the game while he was on the boat, it could be that boat position - -- changed when he left the game vs when he came back. In that case we do nothing. - if not rejoin_data.on_boat then + -- changed when he left the game vs when he came back. + if not (rejoin_data.on_boat and rejoin_data.on_island) then player.teleport(rejoin_surface.find_non_colliding_position('character', rejoin_data.position, 32, 0.5) or memory.spawnpoint, rejoin_surface) end end -- We shouldn't give back items when player was on island, but that island is gone. - if not (rejoin_data.on_island and (not (rejoin_surface and rejoin_surface.valid))) then - Common.give_back_items_to_temporarily_logged_off_player(player) - end + -- Left in case we decide to store player inventory in offline character instead of in the corpse. + -- if not (rejoin_data.on_island and (not (rejoin_surface and rejoin_surface.valid))) then + -- Common.give_back_items_to_temporarily_logged_off_player(player) + -- end memory.temporarily_logged_off_player_data[player.index] = nil end @@ -466,22 +469,24 @@ function Public.leave_crew(player, to_lobby, quiet) -- @TODO: figure out why surface_name can be nil -- When player remains in island when ship leaves, prevent him from getting items back - local save_items = true - if player.surface and - player.surface.valid and - memory.boat and - memory.boat.surface_name - then - if player_surface_type == Surfaces.enum.ISLAND and boat_surface_type == Surfaces.enum.SEA then - save_items = false - end - end + -- local save_items = true + -- if player.surface and + -- player.surface.valid and + -- memory.boat and + -- memory.boat.surface_name + -- then + -- if player_surface_type == Surfaces.enum.ISLAND and boat_surface_type == Surfaces.enum.SEA then + -- save_items = false + -- end + -- end + -- Code regarding item saving is left here if we decide it's better to store items in + -- logged off character as opposed to in the character corpse. if to_lobby then - if save_items then - Common.send_important_items_from_player_to_crew(player, true) - end - char.die(memory.force_name) + -- if save_items then + -- Common.send_important_items_from_player_to_crew(player, true) + -- end + -- char.die(memory.force_name) else if not memory.temporarily_logged_off_player_data then memory.temporarily_logged_off_player_data = {} end @@ -489,15 +494,18 @@ function Public.leave_crew(player, to_lobby, quiet) on_island = (player_surface_type == Surfaces.enum.ISLAND), on_boat = (player_surface_type == boat_surface_type) and Boats.on_boat(memory.boat, player.character.position), surface_name = player.surface.name, - position = player.character.position + position = player.character.position, + tick = game.tick } - if save_items then - Common.temporarily_store_logged_off_character_items(player) - end - memory.temporarily_logged_off_characters[player.index] = game.tick + -- if save_items then + -- Common.temporarily_store_logged_off_character_items(player) + -- end + -- memory.temporarily_logged_off_characters[player.index] = game.tick end + char.die(memory.force_name) + -- else -- if not quiet then -- -- local message = player.name .. ' left the crew.' @@ -509,7 +517,7 @@ function Public.leave_crew(player, to_lobby, quiet) player.set_controller{type = defines.controllers.god} player.teleport(surface.find_non_colliding_position('character', Common.lobby_spawnpoint, 32, 0.5) or Common.lobby_spawnpoint, surface) - player.force = 'player' + player.force = Common.lobby_force_name player.create_character() Event.raise(BottomFrame.events.bottom_quickbar_respawn_raise, {player_index = player.index}) end @@ -588,7 +596,7 @@ function Public.disband_crew(donotprint) for _,player in pairs(players) do if player.controller_type == defines.controllers.editor then player.toggle_map_editor() end - player.force = 'player' + player.force = Common.lobby_force_name end if (not donotprint) then @@ -774,8 +782,9 @@ function Public.initialise_crew(accepted_proposal) memory.spectatorplayerindices = {} memory.tempbanned_from_joining_data = {} memory.destinations = {} - memory.temporarily_logged_off_characters = {} - memory.temporarily_logged_off_characters_items = {} + -- memory.temporarily_logged_off_characters = {} + -- memory.temporarily_logged_off_characters_items = {} + memory.temporarily_logged_off_player_data = {} memory.class_renderings = {} memory.class_auxiliary_data = {} @@ -820,8 +829,8 @@ function Public.initialise_crew(accepted_proposal) memory.officers_table = {} - memory.classes_table = {} -- stores all unlocked untaken classes - memory.spare_classes = {} -- stores all unlocked taken classes + memory.classes_table = {} -- stores all unlocked taken classes + memory.spare_classes = {} -- stores all unlocked untaken classes memory.recently_purchased_classes = {} -- stores recently unlocked classes to add it back to available class pool list later memory.unlocked_classes = {} -- stores all unlocked classes just for GUI (to have consistent order) memory.available_classes_pool = Classes.initial_class_pool() -- stores classes that can be randomly picked for unlocking @@ -909,8 +918,8 @@ function Public.reset_crew_and_enemy_force(id) - crew_force.set_friend('player', true) - game.forces['player'].set_friend(crew_force, true) + crew_force.set_friend(Common.lobby_force_name, true) + game.forces[Common.lobby_force_name].set_friend(crew_force, true) crew_force.set_friend(ancient_friendly_force, true) ancient_friendly_force.set_friend(crew_force, true) enemy_force.set_friend(ancient_friendly_force, true) diff --git a/maps/pirates/gui/crew.lua b/maps/pirates/gui/crew.lua index 53c8e4fb..f577c96e 100644 --- a/maps/pirates/gui/crew.lua +++ b/maps/pirates/gui/crew.lua @@ -512,7 +512,7 @@ function Public.click(event) end if eventname == 'spectator_join_crew' then - Crew.join_crew(player, memory.id) + Crew.join_crew(player) if memory.run_is_protected and (not Roles.captain_exists()) then Common.notify_player_expected(player, {'pirates.player_joins_protected_run_with_no_captain'}) diff --git a/maps/pirates/gui/runs.lua b/maps/pirates/gui/runs.lua index 26a83405..24b210a6 100644 --- a/maps/pirates/gui/runs.lua +++ b/maps/pirates/gui/runs.lua @@ -696,7 +696,11 @@ function Public.click(event) if eventname == 'join_spectators' then local listbox = flow.ongoing_runs.body.ongoing_runs_listbox - Crew.join_spectators(player, tonumber(listbox.get_item(listbox.selected_index)[2])) + -- It was observed that "listbox.get_item(listbox.selected_index)" can produce "Index out of range error" + -- This is to prevent that error. + if listbox.selected_index >= 1 and listbox.selected_index <= #listbox.items then + Crew.join_spectators(player, tonumber(listbox.get_item(listbox.selected_index)[2])) + end return end @@ -713,12 +717,13 @@ function Public.click(event) if listbox.selected_index >= 1 and listbox.selected_index <= #listbox.items then local crewid = tonumber(listbox.get_item(listbox.selected_index)[2]) - local memory = global_memory.crew_memories[crewid] + Memory.set_working_id(crewid) + local memory = Memory.get_crew_memory() -- If run is private - if global_memory.crew_memories[crewid].run_is_private then - if global_memory.crew_memories[crewid].private_run_password == flow.ongoing_runs.body.password_namefield.text then - Crew.join_crew(player, crewid) + if memory.run_is_private then + if memory.private_run_password == flow.ongoing_runs.body.password_namefield.text then + Crew.join_crew(player) flow.ongoing_runs.body.join_private_crew_info.visible = false flow.ongoing_runs.body.password_namefield.visible = false @@ -730,7 +735,7 @@ function Public.click(event) Common.notify_player_error(player, {'pirates.gui_join_private_run_error_wrong_password'}) end else - Crew.join_crew(player, crewid) + Crew.join_crew(player) if memory.run_is_protected and (not Roles.captain_exists()) then Common.notify_player_expected(player, {'pirates.player_joins_protected_run_with_no_captain'}) diff --git a/maps/pirates/memory.lua b/maps/pirates/memory.lua index 3f7cdeec..43e86bda 100644 --- a/maps/pirates/memory.lua +++ b/maps/pirates/memory.lua @@ -86,8 +86,7 @@ function Public.initialise_crew_memory(id) --mostly serves as a dev reference of memory.playerindex_captain = nil memory.captain_accrued_time_data = nil memory.max_players_recorded = nil - memory.temporarily_logged_off_characters = nil - memory.temporarily_logged_off_characters_items = nil + memory.temporarily_logged_off_player_data = nil memory.speed_boost_characters = nil @@ -125,7 +124,7 @@ function Public.fallthrough_crew_memory() --could make this a metatable, but met return { id = 0, difficulty = 1, - force_name = 'player', + force_name = 'player', -- should match Common.lobby_force_name boat = {}, destinations = {}, spectatorplayerindices = {},