mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2025-12-27 03:25:23 +09:00
Make GuiData more lean
This commit is contained in:
@@ -6,28 +6,33 @@ This is not limited to GUI element definitions but this is the most common use c
|
|||||||
local ExpUtil = require("modules/exp_util")
|
local ExpUtil = require("modules/exp_util")
|
||||||
local Storage = require("modules/exp_util/storage")
|
local Storage = require("modules/exp_util/storage")
|
||||||
|
|
||||||
--- @type table<string, ExpGui.GuiData>
|
--- @type table<string, ExpGui.GuiData_Raw>
|
||||||
|
local scope_data = {}
|
||||||
|
|
||||||
|
--- @type table<string, ExpGui.GuiData_Internal>
|
||||||
local registered_scopes = {}
|
local registered_scopes = {}
|
||||||
|
|
||||||
--- @type table<uint, uint> Reg -> Player Index
|
--- @type table<uint, uint> Reg -> Player Index
|
||||||
local registration_numbers = {}
|
local registration_numbers = {}
|
||||||
local reg_obj = script.register_on_object_destroyed
|
local reg_obj = script.register_on_object_destroyed
|
||||||
|
|
||||||
--- @type table<string, [table<uint, table<uint, any>>, table<uint, any>, table<uint, any>, table]>
|
--- @alias DataKey LuaGuiElement | LuaPlayer | LuaForce
|
||||||
local scope_data = {}
|
--- @alias DataKeys "element_data" | "player_data" | "force_data" | "global_data"
|
||||||
|
local DataKeys = ExpUtil.enum{ "element_data", "player_data", "force_data", "global_data" }
|
||||||
|
local DataKeysConcat = table.concat(DataKeys, ", ")
|
||||||
|
|
||||||
Storage.register({
|
Storage.register({
|
||||||
scope_data = scope_data,
|
scope_data = scope_data,
|
||||||
registration_numbers = registration_numbers,
|
registration_numbers = registration_numbers,
|
||||||
}, function(tbl)
|
}, function(tbl)
|
||||||
registration_numbers = tbl.registration_numbers
|
registration_numbers = tbl.registration_numbers
|
||||||
for scope, data in pairs(tbl.scope_data) do
|
for scope, data in pairs(tbl.scope_data) do
|
||||||
local proxy = registered_scopes[scope]
|
local proxy = registered_scopes[scope]
|
||||||
if proxy then
|
if proxy then
|
||||||
proxy.element_data = data[1]
|
rawset(proxy, "_raw", data)
|
||||||
proxy.player_data = data[2]
|
for k, v in pairs(data) do
|
||||||
proxy.force_data = data[3]
|
rawset(proxy, k, v)
|
||||||
proxy.global_data = data[4]
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
@@ -37,43 +42,68 @@ local GuiData = {
|
|||||||
_scopes = registered_scopes,
|
_scopes = registered_scopes,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @alias DataKey LuaGuiElement | LuaPlayer | LuaForce
|
--- @class ExpGui.GuiData_Raw
|
||||||
|
--- @field element_data table<uint, table<uint, any>?>?
|
||||||
|
--- @field player_data table<uint, any>?
|
||||||
|
--- @field force_data table<uint, any>?
|
||||||
|
--- @field global_data table?
|
||||||
|
-- This class has no prototype methods
|
||||||
|
-- Keep this in sync with DataKeys to block arbitrary strings
|
||||||
|
|
||||||
--- @class ExpGui.GuiData: table<DataKey, any>
|
--- @class ExpGui.GuiData_Internal
|
||||||
--- @field _scope string
|
--- @field _scope string
|
||||||
--- @field _owner any
|
--- @field _raw ExpGui.GuiData_Raw
|
||||||
|
-- This class has no prototype methods
|
||||||
|
-- Do add keys to _raw without also referencing scope_data
|
||||||
|
|
||||||
|
--- @class ExpGui.GuiData: table
|
||||||
--- @field element_data table<uint, table<uint, any>>
|
--- @field element_data table<uint, table<uint, any>>
|
||||||
--- @field player_data table<uint, any>
|
--- @field player_data table<uint, any>
|
||||||
--- @field force_data table<uint, any>
|
--- @field force_data table<uint, any>
|
||||||
--- @field global_data table
|
--- @field global_data table
|
||||||
-- This class has no prototype methods
|
-- This class has no prototype methods
|
||||||
|
-- Same as raw but __index ensures the values exist
|
||||||
|
|
||||||
GuiData._metatable = {
|
GuiData._metatable = {
|
||||||
__class = "GuiData",
|
__class = "GuiData",
|
||||||
}
|
}
|
||||||
|
|
||||||
Storage.register_metatable(GuiData._metatable.__class, GuiData._metatable)
|
|
||||||
|
|
||||||
--- Return the index for a given key
|
--- Return the index for a given key
|
||||||
--- @param self ExpGui.GuiData
|
--- @param self ExpGui.GuiData_Internal
|
||||||
--- @param key DataKey
|
--- @param key DataKeys | DataKey
|
||||||
--- @return any
|
--- @return any
|
||||||
function GuiData._metatable.__index(self, key)
|
function GuiData._metatable.__index(self, key)
|
||||||
|
if type(key) == "string" then
|
||||||
|
-- This is only called when the key does not exist, ie it is not in storage
|
||||||
|
-- Once created, these tables are never removed as they are likely to be used again
|
||||||
|
assert(DataKeys[key], "Valid keys are: " .. DataKeysConcat)
|
||||||
|
local value = {}
|
||||||
|
self._raw[key] = value
|
||||||
|
rawset(self, key, value)
|
||||||
|
scope_data[self._scope] = self._raw
|
||||||
|
return value
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check a given child table based on the object type
|
||||||
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
||||||
local object_name = key.object_name
|
local object_name = key.object_name
|
||||||
if object_name == "LuaGuiElement" then
|
if object_name == "LuaGuiElement" then
|
||||||
local player_elements = self.element_data[key.player_index]
|
local data = self._raw.element_data
|
||||||
|
local player_elements = data and data[key.player_index]
|
||||||
return player_elements and player_elements[key.index]
|
return player_elements and player_elements[key.index]
|
||||||
elseif object_name == "LuaPlayer" then
|
elseif object_name == "LuaPlayer" then
|
||||||
return self.player_data[key.index]
|
local data = self._raw.player_data
|
||||||
|
return data and data[key.index]
|
||||||
elseif object_name == "LuaForce" then
|
elseif object_name == "LuaForce" then
|
||||||
return self.force_data[key.index]
|
local data = self._raw.force_data
|
||||||
|
return data and data[key.index]
|
||||||
else
|
else
|
||||||
error("Unsupported object class '" .. object_name .. "' given as index to GuiData.")
|
error("Unsupported object class '" .. object_name .. "' given as index to GuiData.")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the value index of a given key
|
--- Set the value index of a given key
|
||||||
|
-- Internal type is not used here to allow for creation of storage
|
||||||
--- @param self ExpGui.GuiData
|
--- @param self ExpGui.GuiData
|
||||||
--- @param key DataKey
|
--- @param key DataKey
|
||||||
--- @param value unknown
|
--- @param value unknown
|
||||||
@@ -81,10 +111,11 @@ function GuiData._metatable.__newindex(self, key, value)
|
|||||||
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
assert(type(key) == "userdata", "Index type '" .. ExpUtil.get_class_name(key) .. "' given to GuiData. Must be of type userdata.")
|
||||||
local object_name = key.object_name
|
local object_name = key.object_name
|
||||||
if object_name == "LuaGuiElement" then
|
if object_name == "LuaGuiElement" then
|
||||||
local player_elements = self.element_data[key.player_index]
|
local data = self.element_data
|
||||||
|
local player_elements = data[key.player_index]
|
||||||
if not player_elements then
|
if not player_elements then
|
||||||
player_elements = {}
|
player_elements = {}
|
||||||
self.element_data[key.player_index] = player_elements
|
data[key.player_index] = player_elements
|
||||||
end
|
end
|
||||||
player_elements[key.index] = value
|
player_elements[key.index] = value
|
||||||
registration_numbers[reg_obj(key)] = key.player_index
|
registration_numbers[reg_obj(key)] = key.player_index
|
||||||
@@ -106,20 +137,11 @@ function GuiData.create(scope)
|
|||||||
|
|
||||||
local instance = {
|
local instance = {
|
||||||
_scope = scope,
|
_scope = scope,
|
||||||
element_data = {},
|
_raw = {},
|
||||||
player_data = {},
|
|
||||||
force_data = {},
|
|
||||||
global_data = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
scope_data[scope] = {
|
|
||||||
instance.element_data,
|
|
||||||
instance.player_data,
|
|
||||||
instance.force_data,
|
|
||||||
instance.global_data,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiData._scopes[scope] = instance
|
GuiData._scopes[scope] = instance
|
||||||
|
--- @cast instance ExpGui.GuiData
|
||||||
return setmetatable(instance, GuiData._metatable)
|
return setmetatable(instance, GuiData._metatable)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -127,7 +149,7 @@ end
|
|||||||
--- @param scope string
|
--- @param scope string
|
||||||
--- @return ExpGui.GuiData
|
--- @return ExpGui.GuiData
|
||||||
function GuiData.get(scope)
|
function GuiData.get(scope)
|
||||||
return GuiData._scopes[scope]
|
return GuiData._scopes[scope] --[[ @as ExpGui.GuiData ]]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Used to clean up data from destroyed elements
|
--- Used to clean up data from destroyed elements
|
||||||
@@ -140,9 +162,13 @@ local function on_object_destroyed(event)
|
|||||||
registration_numbers[event.registration_number] = nil
|
registration_numbers[event.registration_number] = nil
|
||||||
|
|
||||||
for _, scope in pairs(registered_scopes) do
|
for _, scope in pairs(registered_scopes) do
|
||||||
local player_elements = scope.element_data[player_index]
|
local data = scope._raw.element_data
|
||||||
|
local player_elements = data and data[player_index]
|
||||||
if player_elements then
|
if player_elements then
|
||||||
player_elements[element_index] = nil
|
player_elements[element_index] = nil
|
||||||
|
if not next(player_elements) then
|
||||||
|
data[player_index] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -152,7 +178,10 @@ end
|
|||||||
local function on_player_removed(event)
|
local function on_player_removed(event)
|
||||||
local player_index = event.player_index
|
local player_index = event.player_index
|
||||||
for _, scope in pairs(registered_scopes) do
|
for _, scope in pairs(registered_scopes) do
|
||||||
scope.player_data[player_index] = nil
|
local data = scope._raw.player_data
|
||||||
|
if data then
|
||||||
|
data[player_index] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -161,7 +190,10 @@ end
|
|||||||
local function on_forces_merged(event)
|
local function on_forces_merged(event)
|
||||||
local force_index = event.source_index
|
local force_index = event.source_index
|
||||||
for _, scope in pairs(registered_scopes) do
|
for _, scope in pairs(registered_scopes) do
|
||||||
scope.force_data[force_index] = nil
|
local data = scope._raw.force_data
|
||||||
|
if data then
|
||||||
|
data[force_index] = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user