Add sharedstate.lua
Library for tracking shared variables via pings
This commit is contained in:
parent
16b90916b8
commit
18046a9fcc
157
sharedstate.lua
Normal file
157
sharedstate.lua
Normal file
@ -0,0 +1,157 @@
|
||||
local sharedstate={}
|
||||
logging=require((...):gsub("(.)$", "%1.") .. 'logging')
|
||||
|
||||
-- we're protecting internal variables here, i'm *that* scared of writing bad
|
||||
-- code again.
|
||||
-- this section is purely for making sure the tables are in a consistent state
|
||||
-- maybe this should be a separate library for general state tracking, then i
|
||||
-- could use it in other parts of my code for local state tracking
|
||||
-- (aka how to unnecessarily increase complexity, if i want to do something i
|
||||
-- can just make a function for it)
|
||||
do
|
||||
-- schema: {key: {value: val, old_value: val, callback: function,
|
||||
-- index: integer}}
|
||||
-- wrapping the value in a table should allow the user to store nil
|
||||
local state_table={}
|
||||
|
||||
-- schema: {1: key_name_for_val_1, ...}
|
||||
-- this is to save bandwidth in pings,
|
||||
local state_map={}
|
||||
|
||||
--- Check if initialized
|
||||
-- Check if a key is initialized
|
||||
-- @param key key
|
||||
-- @return true if initialized, else false
|
||||
function is_initialized(key)
|
||||
logging.trace('is_initialized', key)
|
||||
return state_table[key] ~= nil
|
||||
end
|
||||
|
||||
|
||||
--- Internal; ensure key is initialized
|
||||
--Properly initialize a key in all tables.
|
||||
--already initialized
|
||||
--@param key key name
|
||||
--@return true if key has been initialized, false if exists
|
||||
local function init_key(key)
|
||||
logging.trace('init_key', key)
|
||||
if key == nil then
|
||||
error("sharedstate: A key name is required")
|
||||
end
|
||||
|
||||
if is_initialized(key) then
|
||||
return false
|
||||
end
|
||||
-- lua is fucking asinine and starts tables at 1
|
||||
local index=#state_map+1
|
||||
state_map[index]=key
|
||||
|
||||
local tbl={}
|
||||
tbl["index"]=index
|
||||
state_table[key]=tbl
|
||||
return true
|
||||
end
|
||||
|
||||
--- Run callback function
|
||||
-- Run the callback function of the given key
|
||||
-- @param key key
|
||||
function callback_value(key)
|
||||
logging.trace("callback_value", key)
|
||||
local new_value=state_table[key]["value"]
|
||||
local old_value=state_table[key]["old_value"]
|
||||
if type(state_table[key]["callback"]) == "function"
|
||||
and old_value ~= new_value then
|
||||
state_table[key]["callback"](new_value, old_value)
|
||||
end
|
||||
end
|
||||
|
||||
--- Set value and run callback
|
||||
-- Sets a value in the state table, initializing it if neede, and runs
|
||||
-- the callback if it has been previously set
|
||||
-- @param key key
|
||||
-- @param value value
|
||||
-- @param callback callback function
|
||||
function set_value(key, value, callback)
|
||||
logging.trace("set_value", key, value, callback)
|
||||
local initialized=init_key(key)
|
||||
local entry=state_table[key]
|
||||
if initialized then
|
||||
entry["value"]=value
|
||||
entry["old_value"]=value
|
||||
entry["callback"]=callback
|
||||
|
||||
else
|
||||
entry["value"]=value or entry["value"]
|
||||
callback_value(key)
|
||||
entry["callback"]=callback or entry["callback"]
|
||||
entry["old_value"]=value
|
||||
end
|
||||
end
|
||||
|
||||
--- Get value
|
||||
--Get a value from the state table
|
||||
--@param key key
|
||||
--@return value from state table if set, else nil
|
||||
function get_value(key)
|
||||
logging.trace("get_value", key)
|
||||
if not is_initialized(key) then return nil end
|
||||
return state_table[key]["value"]
|
||||
end
|
||||
|
||||
--- Resolve key
|
||||
--Resolve key of given index
|
||||
--@param index index
|
||||
--@return key
|
||||
function resolve_key(index)
|
||||
logging.trace("resolve_key", index)
|
||||
return state_map[index]
|
||||
end
|
||||
|
||||
--- Resolve index
|
||||
--Resolve index of given key
|
||||
--@param key key
|
||||
--@return index
|
||||
function resolve_index(key)
|
||||
logging.trace("resolve_index", key)
|
||||
return state_table[key]["index"]
|
||||
end
|
||||
end
|
||||
|
||||
--- Add an item to the shared state store.
|
||||
--Adds an item to the shared state store, as well as initializes it with a
|
||||
--value. This does not send a ping and should only be used during avatar
|
||||
--initialization.
|
||||
--@param key key name
|
||||
--@param value initial value
|
||||
--@param callback Callback function to run on value change
|
||||
function sharedstate.add(key, value, callback)
|
||||
logging.trace("sharedstate.add", key, value, callback)
|
||||
set_value(key, value, callback)
|
||||
end
|
||||
|
||||
--- Internal; transfer value over network
|
||||
-- Ping used to transfer a value over the network, should not be called
|
||||
-- directly
|
||||
-- @param index Index of key
|
||||
-- @param value New value
|
||||
function pings.sharedstate_transfer(index, value)
|
||||
logging.trace("pings.sharedstate_transfer", index, value)
|
||||
set_value(resolve_key(index), value)
|
||||
end
|
||||
|
||||
--- Set shared value
|
||||
-- Sets a shared value. This sends a ping to transfer it over the network.
|
||||
-- @param key key name
|
||||
-- @param value value
|
||||
function sharedstate.set(key, value)
|
||||
logging.trace("sharedstate.set", key, value)
|
||||
if not is_initialized(key) then
|
||||
error("sharedstate: Key " .. key .. " has not been initialized.")
|
||||
end
|
||||
pings.sharedstate_transfer(resolve_index(key), value)
|
||||
end
|
||||
|
||||
-- this can be copied directly from the internal functions as it is read only
|
||||
sharedstate.get=get_value
|
||||
|
||||
return sharedstate
|
Loading…
x
Reference in New Issue
Block a user