-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
UniversalMethodFinder.luau
121 lines (106 loc) · 2.94 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
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)
hardlimit = nil
depth = nil
printresults = nil
antioverflow = nil
query = nil
end
return finder, globalcontainer