2019-02-02 17:08:09 +02:00
local Global = require ' utils.global '
local type = type
local error = error
local tonumber = tonumber
local tostring = tostring
2019-02-02 17:28:22 +02:00
local pairs = pairs
2019-02-02 17:08:09 +02:00
local format = string.format
--- Contains a set of callables that will attempt to sanitize and transform the input
local settings_type = {
fraction = function ( input )
input = tonumber ( input )
if input == nil then
return false , ' fraction setting type requires the input to be a valid number between 0 and 1. '
end
if input < 0 then
input = 0
end
if input > 1 then
input = 1
end
return true , input
end ,
string = function ( input )
if input == nil then
return true , ' '
end
local input_type = type ( input )
if input_type == ' string ' then
return true , input
end
if input_type == ' number ' or input_type == ' boolean ' then
return true , tostring ( input )
end
return false , ' string setting type requires the input to be either a valid string or something that can be converted to a string. '
end ,
boolean = function ( input )
local input_type = type ( input )
if input_type == ' boolean ' then
return true , input
end
if input_type == ' string ' then
if input == ' 0 ' or input == ' ' or input == ' false ' or input == ' no ' then
return true , false
end
if input == ' 1 ' or input == ' true ' or input == ' yes ' then
return true , true
end
return true , tonumber ( input ) ~= nil
end
if input_type == ' number ' then
return true , input ~= 0
end
return false , ' boolean setting type requires the input to be either a boolean, number or string that can be transformed to a boolean. '
end ,
}
local settings = { }
local memory = { }
Global.register ( memory , function ( tbl ) memory = tbl end )
local Public = { }
2019-02-04 18:37:23 +02:00
Public.types = { fraction = ' fraction ' , string = ' string ' , boolean = ' boolean ' }
2019-02-02 17:08:09 +02:00
---Register a specific setting with a sensitization setting type.
---
--- Available setting types:
--- - fraction (number between 0 and 1) in either number or string form
--- - string a string or anything that can be cast to a string
--- - boolean, 1, 0, yes, no, true, false or an empty string for false
---
2019-02-04 18:37:23 +02:00
--- This function must be called in the control stage, i.e. not inside an event.
2019-02-02 17:08:09 +02:00
---
---@param name string
---@param setting_type string
---@param default mixed
function Public . register ( name , setting_type , default )
2019-02-18 08:43:59 +02:00
if _LIFECYCLE ~= _STAGE.control then
2019-02-04 18:37:23 +02:00
error ( format ( ' You can only register setting names in the control stage, i.e. not inside events. Tried setting "%s" with type "%s". ' , name , setting_type ) , 2 )
2019-02-02 17:08:09 +02:00
end
if settings [ name ] then
2019-02-04 18:37:23 +02:00
error ( format ( ' Trying to register setting for "%s" while it has already been registered. ' , name ) , 2 )
2019-02-02 17:08:09 +02:00
end
local callback = settings_type [ setting_type ]
if not callback then
2019-02-04 18:37:23 +02:00
error ( format ( ' Trying to register setting for "%s" with type "%s" while this type does not exist. ' , name , setting_type ) , 2 )
2019-02-02 17:08:09 +02:00
end
local setting = {
default = default ,
callback = callback ,
}
settings [ name ] = setting
return setting
end
---Sets a setting to a specific value for a player.
---
---In order to get a setting value, it has to be registered via the "register" function.
---
---@param player_index number
---@param name string
---@param value mixed
function Public . set ( player_index , name , value )
local setting = settings [ name ]
if not setting then
2019-02-04 18:37:23 +02:00
return error ( format ( ' Setting "%s" does not exist. ' , name ) , 2 )
2019-02-02 17:08:09 +02:00
end
local success , sanitized_value = setting.callback ( value )
if not success then
2019-02-04 18:37:23 +02:00
error ( format ( ' Setting "%s" failed: %s ' , name , sanitized_value ) , 2 )
2019-02-02 17:08:09 +02:00
end
local player_settings = memory [ player_index ]
if not player_settings then
player_settings = { }
memory [ player_index ] = player_settings
end
player_settings [ name ] = sanitized_value
return sanitized_value
end
---Returns the value of a setting for this player.
---
---In order to set a setting value, it has to be registered via the "register" function.
---
---@param player_index number
---@param name string
function Public . get ( player_index , name )
local setting = settings [ name ]
if not setting then
2019-02-04 18:37:23 +02:00
return error ( format ( ' Setting "%s" does not exist. ' , name ) , 2 )
2019-02-02 17:08:09 +02:00
end
local player_settings = memory [ player_index ]
if not player_settings then
return setting.default
end
local player_setting = player_settings [ name ]
return player_setting ~= nil and player_setting or setting.default
end
2019-02-02 17:28:22 +02:00
---Returns a table of all settings for a given player in a key => value setup
---@param player_index number
function Public . all ( player_index )
local player_settings = memory [ player_index ] or { }
local output = { }
for name , data in pairs ( settings ) do
output [ name ] = player_settings [ name ] or data.default
end
return output
end
2019-02-02 17:08:09 +02:00
return Public