mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 11:35:22 +09:00
Added watch to allow optimistion
This commit is contained in:
@@ -38,4 +38,5 @@ return {
|
|||||||
'config.command_auth_runtime_disable', -- allows commands to be enabled and disabled during runtime
|
'config.command_auth_runtime_disable', -- allows commands to be enabled and disabled during runtime
|
||||||
'config.permission_groups', -- loads some predefined permission groups
|
'config.permission_groups', -- loads some predefined permission groups
|
||||||
'config.roles', -- loads some predefined roles
|
'config.roles', -- loads some predefined roles
|
||||||
|
'expcore.store_test'
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,7 @@ local errors = {}
|
|||||||
for index,path in pairs(files) do
|
for index,path in pairs(files) do
|
||||||
|
|
||||||
-- Loads the next file in the list
|
-- Loads the next file in the list
|
||||||
log(string.format('[INFO] Loading files %3d/%s',index,total_file_count))
|
log(string.format('[INFO] Loading files %3d/%s (%s)',index,total_file_count,path))
|
||||||
local success,file = pcall(require,path)
|
local success,file = pcall(require,path)
|
||||||
|
|
||||||
-- Error Checking
|
-- Error Checking
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
Public.param_check(value,test_type,param_name,param_number) --- Raises an error when the value is the incorrect type, uses a consistent error message format
|
Public.param_check(value,test_type,param_name,param_number) --- Raises an error when the value is the incorrect type, uses a consistent error message format
|
||||||
|
|
||||||
Public.player_return(value,colour,player) --- Will return a value of any type to the player/server console, allows colour for in-game players
|
Public.player_return(value,colour,player) --- Will return a value of any type to the player/server console, allows colour for in-game players
|
||||||
|
Public.write_json(path,tbl) --- Writes a table object to a file in json format
|
||||||
|
|
||||||
Public.opt_require(path) --- Calls a require that will not error if the file is not found
|
Public.opt_require(path) --- Calls a require that will not error if the file is not found
|
||||||
Public.ext_require(path,...) --- Calls a require and returns only the keys given, file must return a table
|
Public.ext_require(path,...) --- Calls a require and returns only the keys given, file must return a table
|
||||||
@@ -94,8 +95,8 @@ function Public.player_return(value,colour,player)
|
|||||||
player = player or game.player
|
player = player or game.player
|
||||||
-- converts the value to a string
|
-- converts the value to a string
|
||||||
local returnAsString
|
local returnAsString
|
||||||
if Public.type_check(value,'table') then
|
if Public.type_check(value,'table') or type(value) == 'userdata' then
|
||||||
if Public.type_check(value.__self,'userdata') then
|
if Public.type_check(value.__self,'userdata') or type(value) == 'userdata' then
|
||||||
-- value is userdata
|
-- value is userdata
|
||||||
returnAsString = 'Cant Display Userdata'
|
returnAsString = 'Cant Display Userdata'
|
||||||
elseif Public.type_check(value[1],'string') and string.find(value[1],'.+[.].+') and not string.find(value[1],'%s') then
|
elseif Public.type_check(value[1],'string') and string.find(value[1],'.+[.].+') and not string.find(value[1],'%s') then
|
||||||
@@ -475,6 +476,9 @@ function Public.enum(tbl)
|
|||||||
table.insert(rtn,v)
|
table.insert(rtn,v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
for k,v in pairs(rtn) do
|
||||||
|
rtn[v]=k
|
||||||
|
end
|
||||||
return rtn
|
return rtn
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -50,10 +50,21 @@
|
|||||||
In a similar way get can be used to get the current value that is stored, if no value is stored then the getter function is called to get the value, this
|
In a similar way get can be used to get the current value that is stored, if no value is stored then the getter function is called to get the value, this
|
||||||
function is more useful when you have custom settings since they would be no other way to access them.
|
function is more useful when you have custom settings since they would be no other way to access them.
|
||||||
|
|
||||||
|
>>>> Optimise the watching
|
||||||
|
When you use player,force or surface you will be checking alot of values for updates for this reason you might want to limit which sub_locations are checked
|
||||||
|
for updates because by default every player/force/surface is checked. You might also want to do this if you want a sub_location that is nil but still want to
|
||||||
|
check for it being updated (because by deafult it only checks non nil sub_locations). To do both these things you will use Store.watch
|
||||||
|
|
||||||
|
Store.watch('force.mining_speed','player')
|
||||||
|
For our force example we dont care about the enemy or neutral force only the player force, so we tell it to watch player and these means that the values for
|
||||||
|
the other forces are not be watched for updates (although Store.get and Store.set will still work). Store.watch will also accept a table of sub_locations in
|
||||||
|
case you want more than one thing to be watch.
|
||||||
|
|
||||||
>>>> Functions:
|
>>>> Functions:
|
||||||
Store.register(location,store_type,getter,setter,no_error) --- Register a new location to store a value, the valu returned from getter will be watched for updates
|
Store.register(location,store_type,getter,setter,no_error) --- Register a new location to store a value, the valu returned from getter will be watched for updates
|
||||||
Store.set(location,sub_location,value) --- Sets the stored values at the location, will call the setter function
|
Store.set(location,sub_location,value) --- Sets the stored values at the location, will call the setter function
|
||||||
Store.get(location,sub_location) --- Gets the value at the location, if the value is nil then the getter function is called
|
Store.get(location,sub_location) --- Gets the value at the location, if the value is nil then the getter function is called
|
||||||
|
Store.watch(location,sub_location,state) --- If used then only sub_locations marked to be watched will be watched for updates, this will also midigate the nil value problem
|
||||||
Store.check(location,sub_location) --- Checks if the store value needs updating, and if true will update it calling the setter function
|
Store.check(location,sub_location) --- Checks if the store value needs updating, and if true will update it calling the setter function
|
||||||
]]
|
]]
|
||||||
|
|
||||||
@@ -61,10 +72,11 @@
|
|||||||
local Global = require 'utils.global'
|
local Global = require 'utils.global'
|
||||||
local Event = require 'utils.event'
|
local Event = require 'utils.event'
|
||||||
local Game = require 'utils.game'
|
local Game = require 'utils.game'
|
||||||
local Enum,write_json = ext_require('expcore.common','enum','write_json')
|
local Enum,write_json,table_keys = ext_require('expcore.common','enum','write_json','table_keys')
|
||||||
|
|
||||||
local Store = {
|
local Store = {
|
||||||
data={},
|
data={},
|
||||||
|
watching={},
|
||||||
locations={},
|
locations={},
|
||||||
types = Enum{
|
types = Enum{
|
||||||
'local', -- data is not stored with any sub_location, updates caused only by set
|
'local', -- data is not stored with any sub_location, updates caused only by set
|
||||||
@@ -75,8 +87,9 @@ local Store = {
|
|||||||
'global' -- data is stored externaly with any sub_location, updates casued by watch, set and the external source
|
'global' -- data is stored externaly with any sub_location, updates casued by watch, set and the external source
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Global.register(Store.data,function(tbl)
|
Global.register({Store.data,Store.watching},function(tbl)
|
||||||
Store.data = table
|
Store.data = tbl[1]
|
||||||
|
Store.watching = tbl[2]
|
||||||
end)
|
end)
|
||||||
|
|
||||||
--- Returns a factorio object for the sub_location
|
--- Returns a factorio object for the sub_location
|
||||||
@@ -96,6 +109,14 @@ local function get_sub_location_object(store_type,sub_location)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns three common parts that are used
|
||||||
|
local function get_location_parts(location,sub_location)
|
||||||
|
location = Store.locations[location]
|
||||||
|
local sub_location_object = get_sub_location_object(location.store_type,sub_location)
|
||||||
|
sub_location = sub_location_object and sub_location_object.name or sub_location
|
||||||
|
return location, sub_location, sub_location_object
|
||||||
|
end
|
||||||
|
|
||||||
--- Emits an event to the external store that a value was updated
|
--- Emits an event to the external store that a value was updated
|
||||||
local function set_global_location_value(location,sub_location,value)
|
local function set_global_location_value(location,sub_location,value)
|
||||||
write_json('log/store.log',{
|
write_json('log/store.log',{
|
||||||
@@ -132,8 +153,7 @@ function Store.set(location,sub_location,value)
|
|||||||
if not Store.locations[location] then
|
if not Store.locations[location] then
|
||||||
return error('The location is not registed: '..location)
|
return error('The location is not registed: '..location)
|
||||||
end
|
end
|
||||||
location = Store.locations[location]
|
local location, sub_location, sub_location_object = get_location_parts(location,sub_location)
|
||||||
local sub_location_object = get_sub_location_object(location.store_type,sub_location)
|
|
||||||
if location.store_type ~= Store.types['local'] then
|
if location.store_type ~= Store.types['local'] then
|
||||||
if not Store.data[location.location] then Store.data[location.location] = {} end
|
if not Store.data[location.location] then Store.data[location.location] = {} end
|
||||||
Store.data[location.location][sub_location] = value
|
Store.data[location.location][sub_location] = value
|
||||||
@@ -142,6 +162,7 @@ function Store.set(location,sub_location,value)
|
|||||||
set_global_location_value(location.location,value)
|
set_global_location_value(location.location,value)
|
||||||
end
|
end
|
||||||
location.setter(sub_location_object or sub_location,value)
|
location.setter(sub_location_object or sub_location,value)
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Gets the value at the location, if the value is nil then the getter function is called
|
--- Gets the value at the location, if the value is nil then the getter function is called
|
||||||
@@ -150,13 +171,33 @@ end
|
|||||||
-- @treturn any the value that was at this location
|
-- @treturn any the value that was at this location
|
||||||
function Store.get(location,sub_location)
|
function Store.get(location,sub_location)
|
||||||
if not Store.locations[location] then return end
|
if not Store.locations[location] then return end
|
||||||
location = Store.locations[location]
|
local location, sub_location, sub_location_object = get_location_parts(location,sub_location)
|
||||||
local sub_location_object = get_sub_location_object(location.store_type,sub_location)
|
|
||||||
local rtn = Store.data[location.location][sub_location]
|
local rtn = Store.data[location.location][sub_location]
|
||||||
if rtn == nil then rtn = location.getter(sub_location_object or sub_location) end
|
if rtn == nil or Store.watching[location.location] and not Store.watching[location.location][sub_location] then
|
||||||
|
rtn = location.getter(sub_location_object or sub_location)
|
||||||
|
end
|
||||||
return rtn
|
return rtn
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- If used then only sub_locations marked to be watched will be watched for updates, this will also midigate the nil value problem
|
||||||
|
-- @tparam location string the location to be returned, must be registed
|
||||||
|
-- @tparam sub_location string sub_location to watch, either string,player,force or surface depending on store type, can be a table of sub_locations
|
||||||
|
-- @tparam[opt=true] state boolean when true it will be marked to be watched, when false it will be removed
|
||||||
|
function Store.watch(location,sub_location,state)
|
||||||
|
if not Store.locations[location] then
|
||||||
|
return error('The location is not registed: '..location)
|
||||||
|
end
|
||||||
|
if type(sub_location) ~= 'table' or type(sub_location.__self) == 'userdata' then
|
||||||
|
sub_location = {sub_location}
|
||||||
|
end
|
||||||
|
for _,v in pairs(sub_location) do
|
||||||
|
if not Store.watching[location] then Store.watching[location] = {} end
|
||||||
|
if state == false then Store.watching[location][v] = nil
|
||||||
|
else Store.watching[location][v] = true end
|
||||||
|
end
|
||||||
|
if #table_keys(Store.watching[location]) == 0 then Store.watching[location] = nil end
|
||||||
|
end
|
||||||
|
|
||||||
--- Checks if the store value needs updating, and if true will update it calling the setter function
|
--- Checks if the store value needs updating, and if true will update it calling the setter function
|
||||||
-- @tparam location string the location to be check, must be registed
|
-- @tparam location string the location to be check, must be registed
|
||||||
-- @tparam sub_location string sub_location to check, either string,player,force or surface depending on store type
|
-- @tparam sub_location string sub_location to check, either string,player,force or surface depending on store type
|
||||||
@@ -165,6 +206,7 @@ function Store.check(location,sub_location)
|
|||||||
if not Store.locations[location] then return false end
|
if not Store.locations[location] then return false end
|
||||||
location = Store.locations[location]
|
location = Store.locations[location]
|
||||||
local sub_location_object = get_sub_location_object(location.store_type,sub_location)
|
local sub_location_object = get_sub_location_object(location.store_type,sub_location)
|
||||||
|
sub_location = sub_location_object and sub_location_object.name or sub_location
|
||||||
local store,getter = Store.data[location.location][sub_location],location.getter(sub_location_object or sub_location)
|
local store,getter = Store.data[location.location][sub_location],location.getter(sub_location_object or sub_location)
|
||||||
if store ~= getter then
|
if store ~= getter then
|
||||||
if not Store.data[location.location] then Store.data[location.location] = {} end
|
if not Store.data[location.location] then Store.data[location.location] = {} end
|
||||||
@@ -177,11 +219,36 @@ end
|
|||||||
|
|
||||||
--- Checks once per second for changes to the store values
|
--- Checks once per second for changes to the store values
|
||||||
Event.on_nth_tick(60,function()
|
Event.on_nth_tick(60,function()
|
||||||
|
local types = {}
|
||||||
for _,location in pairs(Store.locations) do
|
for _,location in pairs(Store.locations) do
|
||||||
if location.store_type ~= Store.types['local'] then
|
if location.store_type ~= Store.types['local'] then
|
||||||
if not Store.data[location.location] then Store.data[location.location] = {} end
|
if not types[location.store_type] then types[location.store_type] = {} end
|
||||||
for sub_location,_ in pairs(Store.data[location.location]) do
|
table.insert(types[location.store_type],location)
|
||||||
Store.check(location,sub_location)
|
end
|
||||||
|
end
|
||||||
|
for store_type,locations in pairs(types) do
|
||||||
|
local keys
|
||||||
|
if store_type == Store.types.player then keys = game.players
|
||||||
|
elseif store_type == Store.types.force then keys = game.forces
|
||||||
|
elseif store_type == Store.types.surface then keys = game.surfaces
|
||||||
|
end
|
||||||
|
if keys then
|
||||||
|
for _,sub_location in pairs(keys) do
|
||||||
|
for _,location in pairs(locations) do
|
||||||
|
if not Store.watching[location.location] or Store.watching[location.location][sub_location.name] then
|
||||||
|
if not Store.data[location.location] then Store.data[location.location] = {} end
|
||||||
|
Store.check(location.location,sub_location)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _,location in pairs(locations) do
|
||||||
|
if not Store.data[location.location] then Store.data[location.location] = {} end
|
||||||
|
if Store.watching[location.location] then keys = Store.watching[location.location]
|
||||||
|
else keys = table_keys(Store.data[location.location]) end
|
||||||
|
for _,sub_location in pairs(keys) do
|
||||||
|
Store.check(location.location,sub_location)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
10
expcore/store_test.lua
Normal file
10
expcore/store_test.lua
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
local Store = require 'expcore.store'
|
||||||
|
|
||||||
|
Store.register('force.mining_speed','force',function(force)
|
||||||
|
return force.manual_mining_speed_modifier
|
||||||
|
end,function(force,value)
|
||||||
|
force.manual_mining_speed_modifier = value
|
||||||
|
game.print(force.name..' how has '..value..' mining speed')
|
||||||
|
end)
|
||||||
|
|
||||||
|
Store.watch('force.mining_speed','player')
|
||||||
Reference in New Issue
Block a user