-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathUniversalMethodFinder.luau
133 lines (116 loc) · 3.16 KB
/
UniversalMethodFinder.luau
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
--!optimize 2
local globalenv = getgenv and getgenv() or _G or shared
local globalcontainer = globalenv.globalcontainer
if not globalcontainer then
globalcontainer = {}
globalenv.globalcontainer = globalcontainer
end
local genvs = { _G, shared } -- Could become an issue if the latest function it gets is unaccessible by client
if getgenv then
table.insert(genvs, getgenv())
end
-- if getrenv then -- Add this if you wish to search through game's env (normal Scripts)
-- table.insert(genvs, 1, getrenv())
-- end
-- if debug and debug.getregistry then
-- table.insert(genvs, 1, debug.getregistry()._LOADED) -- Includes things like string / table / math library tables etc. Basically everything roblox offers, but due to being too huge you should specify library tables by attaching ".string" or to LOADED; adding "_G" to this will link a globals table. That way the finder will have to scan way less.
-- end
local calllimit = 0
do
local function determineCalllimit()
calllimit = calllimit + 1
determineCalllimit()
end
pcall(determineCalllimit)
end
local function isEmpty(dict)
for _ in next, dict do
return
end
return true
end
local depth, printresults, hardlimit, query, antioverflow, matchedall -- prevents infinite / cross-reference
local function recurseEnv(env, envname)
if globalcontainer == env then
return
end
if antioverflow[env] then
return
end
antioverflow[env] = true
depth = depth + 1
for name, val in next, env do
if matchedall then
break
end
local Type = type(val)
if Type == "table" then
if depth < hardlimit then
recurseEnv(val, name)
else
-- warn("almost stack overflow")
end
elseif Type == "function" then -- This optimizes the speeds but if someone manages (??) to fool this then rip
name = string.lower(tostring(name))
local matched
for methodname, pattern in next, query do
if pattern(name, envname) then
globalcontainer[methodname] = val
if not matched then
matched = {}
end
table.insert(matched, methodname)
if printresults then
print(methodname, name)
end
end
end
if matched then
for _, methodname in next, matched do
query[methodname] = nil
end
matchedall = isEmpty(query)
if matchedall then
break
end
end
end
end
depth = depth - 1
end
local function finder(Query, ForceSearch, CustomCallLimit, PrintResults)
antioverflow = {}
query = {}
do -- Load patterns
local function Find(String, Pattern)
return string.find(String, Pattern, nil, true)
end
for methodname, pattern in next, Query do
if not globalcontainer[methodname] or ForceSearch then
if not Find(pattern, "return") then
pattern = "return " .. pattern
end
query[methodname] = loadstring(pattern)
end
end
end
depth = 0
printresults = PrintResults
hardlimit = CustomCallLimit or calllimit
recurseEnv(genvs)
-- fallback to __index inheritance
do
local env = getfenv()
for methodname in next, Query do
if not globalcontainer[methodname] then
globalcontainer[methodname] = env[methodname]
end
end
end
hardlimit = nil
depth = nil
printresults = nil
antioverflow = nil
query = nil
end
return finder, globalcontainer