-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathregistry.lua
More file actions
135 lines (112 loc) · 4.43 KB
/
Copy pathregistry.lua
File metadata and controls
135 lines (112 loc) · 4.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
-- ui/registry.lua
local log = function(msg, ...) minetest.log("action", "[ui.registry] " .. msg:format(...)) end
local function assert_instance(self)
assert(self._is_registry_instance, "Registry method called on class table! Use :new() to create an instance.")
end
local Registry = {}
Registry.__classname = "Registry"
function Registry:new(label, opts)
opts = opts or {}
assert(type(label) == "string" and label ~= "",
"[Registry] Must provide a non-empty label string")
if rawget(self, "_is_registry_instance") then
error("[Registry] :new() called on an instance")
end
local obj = {
data = {},
_label = label,
_is_registry_instance = true,
_allow_functions = opts.allow_functions or false,
}
setmetatable(obj, { __index = self })
log("[Registry] NEW instance '%s' created at:\n%s", obj._label, debug.traceback())
return obj
end
function Registry:getlabel()
return self._label;
end
function Registry:set(user, form, key, value)
assert_instance(self)
log("Registry[%s]: self = %s, metatable index = %s, data table = %s", self._label, tostring(self), tostring(getmetatable(self) and getmetatable(self).__index), tostring(self.data))
assert(self._is_registry_instance, "Registry:set called on class instead of instance")
log("SET (instance="..tostring(self)..") called from:\n" .. debug.traceback())
-- Log every set
log(("SET: user=%s form=%s key=%s value=%s (type=%s)"):format(
tostring(user), tostring(form), tostring(key), tostring(value), type(value)))
assert(key, "Registry:set called with nil key")
if type(value) == "function" and not self._allow_functions then
minetest.log("error", ("[ui.registry] !!! ERROR: Attempted to store FUNCTION in registry[%s] at key=%s\nSTACK:\n%s"):format(self._label, key, debug.traceback()))
end
-- Special warning if a function is being stored!
if self._label == "state" and type(value) == "function" then
log("!!! BUG: Attempted to store FUNCTION in state registry '%s'", self._label)
end
if not user or not form or not key then
log("Registry:set called with user=", tostring(user), "form=", tostring(form), "key=", tostring(key), "value=", tostring(value))
debug.traceback()
end
assert(user, "Registry:set called with nil user")
assert(form, "Registry:set called with nil form")
self.data[user] = self.data[user] or {}
self.data[user][form] = self.data[user][form] or {}
self.data[user][form][key] = value
end
function Registry:get(user, form, key)
assert_instance(self)
log("Registry[%s]: self = %s, metatable index = %s, data table = %s", self._label, tostring(self), tostring(getmetatable(self) and getmetatable(self).__index), tostring(self.data))
log("GET (instance="..tostring(self)..") called from:\n" .. debug.traceback())
local val = self.data[user] and self.data[user][form] and self.data[user][form][key]
log(("GET: user=%s form=%s key=%s => %s (type=%s)"):format(
tostring(user), tostring(form), tostring(key), tostring(val), type(val)))
if type(val) == "function" then
log(("!!! BUG: Retrieved FUNCTION from state registry: user=%s form=%s key=%s STACK:\n%s"):format(
tostring(user), tostring(form), tostring(key), debug.traceback()))
end
return val
end
function Registry:delete(user, form, key)
assert_instance(self)
if self.data[user] and self.data[user][form] then
self.data[user][form][key] = nil
end
end
function Registry:clear_user(user)
self.data[user] = nil
end
function Registry:clear_user_form(user, form)
if self.data[user] then
self.data[user][form] = nil
-- Optionally remove user table if now empty
if next(self.data[user]) == nil then
self.data[user] = nil
end
end
log("Cleared form '%s' for user '%s'", form, user)
end
function Registry:clear_form_all_users(form)
for user, forms in pairs(self.data) do
forms[form] = nil
if next(forms) == nil then
self.data[user] = nil
end
end
end
function Registry:clear_all()
self.data = {}
end
-- Optional: Iterate over all keys for a user/form (for batch expiration)
function Registry:for_each_user_form(user, form, fn)
if self.data[user] and self.data[user][form] then
for k, v in pairs(self.data[user][form]) do
fn(k, v)
end
end
end
-- At the end of registry.lua
-- At the end of registry.lua
setmetatable(Registry, {
__newindex = function(_, k, v)
error("[Registry] Attempt to write '" .. tostring(k) .. "' on Registry class — this is forbidden.")
end,
})
return Registry