|
| 1 | +--[[ |
| 2 | + This is just a particular example, not a guide. You don't have to follow this example forever! |
| 3 | +
|
| 4 | + We gonna use https://lua-api.factorio.com/latest/Global.html to store data and some local table for singleplayer in some cases. |
| 5 | +
|
| 6 | + There are some subtle differences between singleplayer and multiplayer. |
| 7 | + For instance: when a player start a map in singleplayer, the script won't use some events: |
| 8 | + defines.events.on_player_joined_game -- it works only when a player joins first time in singleplayer |
| 9 | + defines.events.on_player_left_game |
| 10 | +
|
| 11 | + That leads some issues in other events. |
| 12 | + Usually, it's not a problem if data doesn't depend on those events or some related data isn't empty. |
| 13 | + We might use on_init and on_configuration_changed to always have some data. |
| 14 | + But it depends on your cases etc. |
| 15 | +
|
| 16 | + So, in this example, we don't store data in global for players when they are offline and we're not going to "adapt" the data for singleplayer. |
| 17 | +]] |
| 18 | + |
| 19 | + |
| 20 | +local module = {} |
| 21 | + |
| 22 | + |
| 23 | +--#region Singleplayer data |
| 24 | +-- Usually, some tables here (it's like a mirror of global data for singleplayer) |
| 25 | +local sp_player_data = {} |
| 26 | +--#endregion |
| 27 | + |
| 28 | + |
| 29 | +--#region Global data |
| 30 | +local players_data |
| 31 | +--#endregion |
| 32 | + |
| 33 | +--#region Functions of events |
| 34 | + |
| 35 | +local function on_player_joined_game(event) |
| 36 | + local player_index = event.player_index |
| 37 | + local player = game.get_player(player_index) |
| 38 | + if not (player and player.valid) then return end |
| 39 | + |
| 40 | + -- Trying to simulate "loaded" game without this mod (otherwise I have to tell you about other cases) |
| 41 | + if game.is_multiplayer() then |
| 42 | + players_data[player_index] = {} |
| 43 | + end |
| 44 | +end |
| 45 | + |
| 46 | +local function delete_player_data(event) |
| 47 | + players_data[event.player_index] = nil |
| 48 | +end |
| 49 | + |
| 50 | +local function on_cancelled_deconstruction(event) |
| 51 | + local player_index = event.player_index |
| 52 | + local player = game.get_player(player_index) |
| 53 | + if not (player and player.valid) then return end |
| 54 | + |
| 55 | + local data = players_data[player_index] or sp_player_data |
| 56 | + -- You might get rid of second variable but, sometimes, it'll lead to more complex code or less performance |
| 57 | + |
| 58 | + data[#data] = math.random(100) -- it's safe to generate random numbers in multiplayer |
| 59 | + player.print("Data: " .. serpent.line(data)) |
| 60 | + -- Let's check the result |
| 61 | + if players_data[player_index] == nil then |
| 62 | + player.print("Nothing in global data for player, using \"singleplayer\" data") |
| 63 | + else |
| 64 | + player.print("Using global to store the data") |
| 65 | + end |
| 66 | +end |
| 67 | + |
| 68 | +--#endregion |
| 69 | + |
| 70 | + |
| 71 | +--#region Pre-game stage |
| 72 | + |
| 73 | +local function link_data() |
| 74 | + players_data = global.players |
| 75 | +end |
| 76 | + |
| 77 | +local function update_global_data() |
| 78 | + global.players = global.players or {} |
| 79 | + |
| 80 | + for player_index, _ in pairs(game.players) do |
| 81 | + global.players[player_index] = nil |
| 82 | + end |
| 83 | +end |
| 84 | + |
| 85 | + |
| 86 | +module.on_init = (function() |
| 87 | + update_global_data() |
| 88 | + link_data() |
| 89 | +end) |
| 90 | + |
| 91 | +module.on_load = (function() |
| 92 | + link_data() |
| 93 | +end) |
| 94 | + |
| 95 | +module.on_configuration_changed = (function() |
| 96 | + update_global_data() |
| 97 | + link_data() |
| 98 | +end) |
| 99 | +module.update_global_data_on_disabling = update_global_data -- for safe disabling |
| 100 | + |
| 101 | +--#endregion |
| 102 | + |
| 103 | + |
| 104 | +---@type table<number|string, function> |
| 105 | +-- [optional] |
| 106 | +-- All events of https://lua-api.factorio.com/latest/events.html#All%20events except on_nth_tick |
| 107 | +module.events = { |
| 108 | + --[defines.events.on_player_created] = on_player_created, -- it might be useful |
| 109 | + [defines.events.on_player_joined_game] = on_player_joined_game, |
| 110 | + [defines.events.on_player_left_game] = delete_player_data, |
| 111 | + [defines.events.on_player_removed] = delete_player_data, |
| 112 | + [defines.events.on_cancelled_deconstruction] = on_cancelled_deconstruction |
| 113 | +} |
| 114 | + |
| 115 | + |
| 116 | +---@type table<string, function> |
| 117 | +-- [optional] |
| 118 | +-- Check folder "command-wrapper" |
| 119 | +module.commands = { |
| 120 | + -- set_spawn = set_spawn_command, -- Delete this example |
| 121 | +} |
| 122 | + |
| 123 | + |
| 124 | +return module |
0 commit comments