diff --git a/config/_file_loader.lua b/config/_file_loader.lua index c6ea3ff9..bb45f8e7 100644 --- a/config/_file_loader.lua +++ b/config/_file_loader.lua @@ -6,7 +6,9 @@ return { --'example.file_not_loaded', 'modules.factorio-control', -- base factorio free play scenario - -- Game Commands + 'expcore.playerdata', + + --- Game Commands 'modules.commands.me', 'modules.commands.kill', 'modules.commands.admin-chat', @@ -28,7 +30,8 @@ return { 'modules.commands.bonus', 'modules.commands.home', 'modules.commands.quickbar', - -- QoL Addons + + --- Addons 'modules.addons.station-auto-name', 'modules.addons.greetings', 'modules.addons.chat-popups', @@ -43,7 +46,8 @@ return { 'modules.addons.discord-alerts', 'modules.addons.chat-reply', 'modules.addons.tree-decon', - -- GUI + + --- GUI 'modules.gui.readme', 'modules.gui.rocket-info', 'modules.gui.science-info', @@ -52,7 +56,8 @@ return { 'modules.gui.player-list', 'modules.gui.server-ups', 'modules.commands.debug', - -- Config Files + + --- Config Files 'config.expcore.command_auth_admin', -- commands tagged with admin_only are blocked for non admins 'config.expcore.command_auth_roles', -- commands must be allowed via the role config 'config.expcore.command_runtime_disable', -- allows commands to be enabled and disabled during runtime diff --git a/config/expcore/command_general_parse.lua b/config/expcore/command_general_parse.lua index 7b9e282a..9cbf9a72 100644 --- a/config/expcore/command_general_parse.lua +++ b/config/expcore/command_general_parse.lua @@ -40,12 +40,12 @@ end) Commands.add_parse('string-options',function(input,player,reject,options) if not input then return end -- nil check input = input:lower() - for option in options do + for _, option in ipairs(options) do if input == option:lower() then - return true + return option end end - return reject{'reject-string-options',options:concat(', ')} + return reject{'expcore-commands.reject-string-options', table.concat(options, ', ')} end) Commands.add_parse('string-max-length',function(input,player,reject,max_length) diff --git a/config/expcore/roles.lua b/config/expcore/roles.lua index 7d1fd4e1..578e2a8e 100644 --- a/config/expcore/roles.lua +++ b/config/expcore/roles.lua @@ -220,6 +220,8 @@ local default = Roles.new_role('Guest','') 'command/report', 'command/ratio', 'command/server-ups', + 'command/data-policy', + 'command/set-data-policy', 'gui/player-list', 'gui/rocket-info', 'gui/science-info', diff --git a/expcore/datastore.lua b/expcore/datastore.lua index 0c6c22c9..863933a1 100644 --- a/expcore/datastore.lua +++ b/expcore/datastore.lua @@ -4,6 +4,7 @@ local Event = require 'utils.event' --- @dep utils.event local DatastoreManager = {} local Datastores = {} local Datastore = {} +local copy = table.deep_copy --- Save datastores in the global table global.datastores = Datastores @@ -129,6 +130,15 @@ function Datastore:write_action(action, key, value) game.write_file('datastore.pipe', table.concat(data, ' ')..'\n', true, 0) end +--- Set a callback that will be used to serialize keys which aren't strings +function Datastore:set_serializer(callback) + assert(type(callback) == 'function', 'Callback must be a function') + self.serializer = callback +end + +--- Create a new datastore which is combined into this one +Datastore.combine = DatastoreManager.combine + --- Request a value from an external source function Datastore:request(key) if self.combined then return self.combined:request(key) end @@ -138,11 +148,11 @@ end --- Save a value to an external source function Datastore:save(key) - if self.combined then return self.combined:save(key) end + if self.combined then self.combined:save(key) end if not self.save_to_disk then return end key = self:serialize(key) local value = self:raw_get(key) - value = self:raise_event('on_save', key, value) + value = self:raise_event('on_save', key, copy(value)) local action = self.propagateChanges and 'propagate' or 'save' self:write_action(action, key, value) end @@ -151,6 +161,7 @@ end function Datastore:unload(key) if self.combined then return self.combined:unload(key) end key = self:serialize(key) + self:raise_event('on_unload', key, copy(self:raw_get(key))) self:save(key) self:raw_set(key) end @@ -174,7 +185,7 @@ function Datastore:get(key, default) key = self:serialize(key) local value = self:raw_get(key) if value ~= nil then return value end - return table.deep_copy(default) + return copy(default) end --- Set a value in local storage @@ -245,12 +256,6 @@ function Datastore:unload_all(callback) for key in pairs(data) do self:unload(key) end end ---- Set a callback that will be used to serialize keys which aren't strings -function Datastore:set_serializer(callback) - assert(type(callback) == 'function', 'Callback must be a function') - self.serializer = callback -end - ----- Events ----- -- @section events diff --git a/expcore/playerdata.lua b/expcore/playerdata.lua new file mode 100644 index 00000000..f400f4ca --- /dev/null +++ b/expcore/playerdata.lua @@ -0,0 +1,63 @@ + +local Event = require 'utils.event' --- @dep utils.event +local Datastore = require 'expcore.datastore' --- @dep expcore.datastore +local Commands = require 'expcore.commands' --- @dep expcore.commands +require 'config.expcore.command_general_parse' --- @dep config.expcore.command_general_parse + +--- Common player data that acts as the root store for player data +local PlayerData = Datastore.connect('PlayerData', true) -- saveToDisk +PlayerData:set_serializer(Datastore.name_serializer) -- use player name + +--- Store and enum for the data collection policy +local DataCollectionPolicy = PlayerData:combine('DataCollectionPolicy') +local PolicyEnum = { 'All', 'Tracking', 'Settings', 'Required' } +for k,v in ipairs(PolicyEnum) do PolicyEnum[v] = k end + +--- Sets your data collection policy +-- @command set-data-policy +Commands.new_command('set-data-policy', 'Allows you to set your data collection policy') +:add_param('option', false, 'string-options', PolicyEnum) +:register(function(player, option) + DataCollectionPolicy:set(player, option) + return {'expcore-data.set-policy', option} +end) + +--- Gets your data collection policy +-- @command data-policy +Commands.new_command('data-policy', 'Shows you what your current data collection policy is') +:register(function(player) + return {'expcore-data.get-policy', DataCollectionPolicy:get(player, 'All')} +end) + +--- Remove data that the player doesnt want to have stored +PlayerData:on_save(function(player_name, player_data) + local collectData = DataCollectionPolicy:get(player_name, 'All') + collectData = PolicyEnum[collectData] + if collectData == PolicyEnum.All then return player_data end + + local saved_player_data = { PlayerRequired = player_data.PlayerRequired, DataCollectionPolicy = PolicyEnum[collectData] } + if collectData <= PolicyEnum.Settings then saved_player_data.PlayerSettings = player_data.PlayerSettings end + if collectData <= PolicyEnum.Tracking then saved_player_data.PlayerTracking = player_data.PlayerTracking end + + return saved_player_data +end) + +--- Load player data when they join +Event.add(defines.events.on_player_joined_game, function(event) + PlayerData:request(game.players[event.player_index]) +end) + +--- Unload player data when they leave +Event.add(defines.events.on_player_left_game, function(event) + PlayerData:unload(game.players[event.player_index]) +end) + +----- Module Return ----- +return { + All = PlayerData, -- Root for all of a players data + Tracking = PlayerData:combine('PlayerTracking'), -- Common place for tracing stats + Settings = PlayerData:combine('PlayerSettings'), -- Common place for settings + Required = PlayerData:combine('PlayerRequired'), -- Common place for required data + DataCollectionPolicy = DataCollectionPolicy, -- Stores what data groups will be saved + PolicyEnum = PolicyEnum -- Enum for the allowed options for the data collection policy +} \ No newline at end of file diff --git a/locale/en/expcore.cfg b/locale/en/expcore.cfg index ce4d3d45..ea0a5d0c 100644 --- a/locale/en/expcore.cfg +++ b/locale/en/expcore.cfg @@ -36,3 +36,7 @@ button_tooltip=Shows/hides the toolbar. [expcore-gui] left-button-tooltip=Hide all open windows. + +[expcore-data] +set-policy=You data collection policy has been set to __1__. Existing data will not be effected until you rejoin. +get-policy=You data collection policy is __1__. Use /set-data-policy to change this. \ No newline at end of file