2021-03-02 21:01:39 +00:00
-- This feature allows you to turn on anti-hoarding so that X minutes after a player leaves the game
2021-03-02 21:09:19 +00:00
-- the resources in their inventory are returned to the teams. A corpse will spawn on the player's last
-- position and remain until they log back in to claim it or someone else mines it.
2024-08-28 22:37:04 +02:00
-- All players will drop their armors and weapons during the first 24h of the game,
-- after this time, only regulars and above will keep their armor and just drop the inventory.
2021-03-02 20:46:42 +00:00
local Event = require ' utils.event '
local Task = require ' utils.task '
local Token = require ' utils.token '
2021-03-03 18:52:30 +00:00
local Global = require ' utils.global '
2021-03-03 20:13:25 +00:00
local CorpseUtil = require ' features.corpse_util '
2022-01-04 20:53:31 +00:00
local Config = require ' config '
2024-08-28 22:37:04 +02:00
local Rank = require ' features.rank_system '
local Ranks = require ' resources.ranks '
local MINS_TO_TICKS = 60 * 60
local HOUR_TO_TICKS = MINS_TO_TICKS * 60
local DEFAULT_OFFLINE_TIMEOUT_MINS = 15
local DEFAULT_STARTUP_GEAR_DROP_HOURS = 24
2021-03-02 20:46:42 +00:00
local set_timeout_in_ticks = Task.set_timeout_in_ticks
2022-01-04 20:53:31 +00:00
local config = Config.dump_offline_inventories
2021-03-02 20:46:42 +00:00
2021-03-03 18:52:30 +00:00
local offline_player_queue = { }
2021-12-29 16:28:39 +00:00
2022-01-04 20:53:31 +00:00
Global.register ( { offline_player_queue = offline_player_queue } , function ( tbl )
2021-12-29 16:28:39 +00:00
offline_player_queue = tbl.offline_player_queue
2022-01-04 20:53:31 +00:00
config = Config.dump_offline_inventories
2021-03-03 18:52:30 +00:00
end )
2021-03-02 20:46:42 +00:00
2022-01-04 20:53:31 +00:00
local function spawn_player_corpse ( player , banned , timeout_minutes )
2021-12-29 16:28:39 +00:00
local player_index = player.index
offline_player_queue [ player_index ] = nil
2022-01-04 20:53:31 +00:00
if not banned and player.connected then
2021-12-29 16:28:39 +00:00
return
end
2024-08-28 22:37:04 +02:00
local inventory_types = {
defines.inventory . character_main ,
defines.inventory . character_guns ,
defines.inventory . character_ammo ,
defines.inventory . character_vehicle ,
defines.inventory . character_trash ,
}
2022-01-25 19:59:12 +00:00
2024-08-28 22:37:04 +02:00
local startup_gear_drop_hours = config.startup_gear_drop_hours or DEFAULT_STARTUP_GEAR_DROP_HOURS
if banned or game.tick < ( startup_gear_drop_hours * HOUR_TO_TICKS ) or Rank.less_than ( player.name , Ranks.regular ) then
table.insert ( inventory_types , defines.inventory . character_armor )
2022-01-25 19:59:12 +00:00
end
2021-12-29 16:28:39 +00:00
2024-08-28 22:37:04 +02:00
local inv_contents = { }
for _ , id in pairs ( inventory_types ) do
local inv = player.get_inventory ( id )
if inv and inv.valid then
for i = 1 , # inv do
local item_stack = inv [ i ]
if item_stack.valid_for_read then
table.insert ( inv_contents , item_stack )
end
end
end
2022-01-25 19:59:12 +00:00
end
2021-12-29 16:28:39 +00:00
2024-08-28 22:37:04 +02:00
if # inv_contents == 0 then
2021-12-29 16:28:39 +00:00
return
end
2024-10-22 21:22:35 +02:00
local position = player.physical_position
local corpse = player.physical_surface . create_entity {
2024-08-28 22:37:04 +02:00
name = ' character-corpse ' ,
2021-12-29 16:28:39 +00:00
position = position ,
2024-08-28 22:37:04 +02:00
inventory_size = # inv_contents ,
2021-12-29 16:28:39 +00:00
player_index = player_index
}
corpse.active = false
local inv_corpse = corpse.get_inventory ( defines.inventory . character_corpse )
2024-08-28 22:37:04 +02:00
for _ , item_stack in pairs ( inv_contents ) do
inv_corpse.insert ( item_stack )
2021-12-29 16:28:39 +00:00
end
2024-08-28 22:37:04 +02:00
for _ , id in pairs ( inventory_types ) do
local inv = player.get_inventory ( id )
if inv and inv.valid then
inv.clear ( )
end
2022-01-25 19:59:12 +00:00
end
2021-12-29 16:28:39 +00:00
local text = player.name .. " 's inventory (offline) "
local tag = player.force . add_chart_tag ( player.surface , {
icon = { type = ' item ' , name = ' modular-armor ' } ,
position = position ,
text = text
} )
2022-01-04 20:53:31 +00:00
local message
if banned then
message = {
' dump_offline_inventories.banned_inventory_location ' ,
player.name ,
string.format ( ' %.1f ' , position.x ) ,
string.format ( ' %.1f ' , position.y ) ,
player.surface . name
}
else
message = {
' dump_offline_inventories.inventory_location ' ,
player.name ,
timeout_minutes ,
string.format ( ' %.1f ' , position.x ) ,
string.format ( ' %.1f ' , position.y ) ,
player.surface . name
}
end
2021-12-29 16:28:39 +00:00
game.print ( message )
if tag then
CorpseUtil.add_tag ( tag , player_index , game.tick , false )
end
2022-01-04 20:53:31 +00:00
end
local spawn_player_corpse_token = Token.register ( function ( data )
local player = data.player
if not player or not player.valid then
return
end
local queue_data = offline_player_queue [ player.index ]
if queue_data ~= data.tick then
return
end
spawn_player_corpse ( player , false , data.timeout_minutes )
2021-12-29 16:28:39 +00:00
end )
2021-03-02 20:46:42 +00:00
2022-01-04 20:53:31 +00:00
local function start_timer ( event , timeout_minutes )
2021-03-03 20:13:25 +00:00
local player_index = event.player_index
local player = game.get_player ( player_index )
2021-03-02 20:46:42 +00:00
2022-01-04 20:53:31 +00:00
if player and player.valid and player.character then -- if player leaves before respawning they wont have a character and we don't need to add them to the list.
2021-03-03 20:13:25 +00:00
local tick = game.tick
2024-08-28 22:37:04 +02:00
local timeout = timeout_minutes * MINS_TO_TICKS
2022-01-04 20:53:31 +00:00
2021-12-29 16:28:39 +00:00
offline_player_queue [ player_index ] = tick -- tick is used to check that the callback happens after X minutes as multiple callbacks may be active if the player logs off and on multiple times
2022-01-04 20:53:31 +00:00
set_timeout_in_ticks ( timeout , spawn_player_corpse_token ,
{ player = player , tick = tick , timeout_minutes = timeout_minutes } )
2021-03-03 18:52:30 +00:00
end
2021-03-03 20:13:25 +00:00
end
2021-03-03 18:52:30 +00:00
2021-03-03 20:13:25 +00:00
Event.add ( defines.events . on_pre_player_left_game , function ( event )
2022-01-04 20:53:31 +00:00
if not config.enabled then
2021-12-29 16:28:39 +00:00
return
end
2024-08-28 22:37:04 +02:00
start_timer ( event , config.offline_timeout_mins or DEFAULT_OFFLINE_TIMEOUT_MINS )
2021-03-03 20:13:25 +00:00
end )
Event.add ( defines.events . on_player_banned , function ( event )
2022-05-01 15:51:17 +01:00
local player_index = event.player_index
if not player_index then
return
end
2022-01-04 20:53:31 +00:00
local player = game.get_player ( event.player_index )
if not player or not player.valid then
2021-12-29 16:28:39 +00:00
return
end
2022-01-04 20:53:31 +00:00
spawn_player_corpse ( player , true , 0 )
2021-12-29 16:28:39 +00:00
end )