Run it
Copy the script and paste it into your executor.
M = {
version = , dead = , generation = , mining = , scanning = , deepScanning = ,
connections = {}, rows = {}, workers = {}, entries = {}, catalog = {}, observed = {},
categories = {}, logs = {}, filter = , category = , query = ,
page = , pageSize = , selected = , busy = , nextRequest = ,
source = , coverage = , rawConfig = , remoteTree = , deepStats = {},
handoffDonorName = , lastIncomingOffer = ,
colors = {
bg = .(, , ), panel = .(, , ),
row = .(, , ), active = .(, , ),
text = .(, , ), muted = .(, , ),
accent = .(, , ), good = .(, , ),
bad = .(, , ), line = .(, , )
}
}
M.(value)
(value) == value ~=
M.(value)
(value) == ((value) == value:())
.. (value)
(value) == value
M.(value)
(value):(, ):()
M.(root, path)
node = root
segment (path):()
(node) ~=
nextNode = node[segment]
nextNode ==
key, value (node)
(key) == M.(key) == M.(segment)
nextNode = value
nextNode ==
node = nextNode
node
M.(packages, defaultPackage)
(packages) ~=
roots, seen = {}, {}
(name, value)
(value) == seen[value]
seen[value] =
roots[#roots + ] = {name = name, value = value}
(, packages.brookhaven)
key, value (packages)
(key) == key:() == (key, value)
(defaultPackage) == (defaultPackage, packages[defaultPackage])
keys = {}
key (packages) keys[#keys + ] = key
.(keys, (a, b) (a) < (b) )
_, key (keys) ((key), packages[key])
(, packages)
_, candidate (roots)
config = M.(candidate.value, )
(config) == config, candidate.name
M.(value)
(value) == value
out = {}
(value) ==
key, item (value)
(item) == out[#out + ] = item
item == (key) == out[#out + ] = key
.(out)
.(out, )
M.(config, source)
entries, categories, stats = {}, {}, {rows = , tools = , categories = , skipped = , duplicates = }
(config) ~= entries, categories, stats
keys = {}
key (config) keys[#keys + ] = key
.(keys, (a, b) (a) < (b) )
_, key (keys)
raw = config[key]
stats.rows = stats.rows +
(raw) ==
name = M.(raw.Name) raw.Name ((key) == key )
name name ~= name ~=
entries[name]
stats.duplicates = stats.duplicates +
isCategory = raw.IsCategory ==
gun = M.(raw.GunSkin) raw.GunSkin
item = M.(raw.Item) raw.Item
requirement = raw.RequirementBehaviorData
e = {
name = name, displayName = M.(raw.DisplayName) raw.DisplayName name,
category = M.(raw.Category) raw.Category ,
icon = M.(raw.Icon raw.IconWhenUnlocked),
order = (raw.Order) , isCategory = isCategory,
kind = isCategory (gun ),
route = isCategory (gun ) ,
gunSkin = gun, item = item, filters = M.(raw.Filter),
requirement = (requirement) == (requirement.Behavior ) ,
hiddenUnlessUnlocked = raw.HiddenUnlessUnlocked == ,
source = source, raw = raw, catalog =
}
entries[name] = e
isCategory
categories[name] = e
stats.categories = stats.categories +
stats.tools = stats.tools +
stats.skipped = stats.skipped +
stats.skipped = stats.skipped +
entries, categories, stats
M.(entry, categories)
parts, seen, current = {}, {}, entry.category
current current ~= seen[current]
seen[current] =
.(parts, , categories[current] categories[current].displayName current)
current = categories[current] categories[current].category
#parts > .(parts, )
M.(entry, wanted, categories)
wanted ==
seen, current = {}, entry.category
entry.isCategory entry.name == wanted
current current ~= seen[current]
current == wanted
seen[current] =
current = categories[current] categories[current].category
M.(entry, query)
haystack = .({entry.name, entry.displayName, entry.kind, entry.category,
entry.categoryPath , entry.filters , entry.item , entry.source }, ):()
word query:():()
haystack:(word, , )
M.(entry)
entry.isCategory
entry.route == M.(entry.gunSkin)
, {entry.gunSkin, entry.name}
entry.route ==
, {, entry.name}
M.(entry, intent, present, busy)
entry.isCategory
intent == present
intent == present
intent == present
busy
M.(entry)
(intent == intent == ) entry.interactions #entry.interactions >
M.Players = :()
M.RS = :()
M.Input = :()
M.Http = :()
M.Tags = :()
M.Player = M.Players.LocalPlayer
M.Player ()
M.PlayerGui = M.Player:(, )
M.PlayerGui ()
M.env = (() == ())
(M.env.ToolMinerSpawnerUnload) == (M.env.ToolMinerSpawnerUnload)
M.started = .()
M.(connection, list)
target = list M.connections
target[#target + ] = connection
connection
M.(list)
_, connection (list) (() connection:() )
.(list)
M.(message)
M.dead
line = .(, .() - M.started, (message))
M.logs[#M.logs + ] = line
#M.logs > .(M.logs, )
( .. line)
M.modalMode == M.ui M.ui.exportBox
(() M.ui.exportBox.Text = .(M.logs, ) )
M.(message, state)
M.dead M.ui M.ui.status
(()
M.ui.status.Text = message
M.ui.status.TextColor3 = state == M.colors.good (state == M.colors.bad M.colors.muted)
)
M.(callback)
M.dead
thread
thread = .(()
ok, err = (callback, debug.traceback)
M.workers[.()] =
ok M.dead
M.(err)
M.(, )
)
M.workers[thread] =
thread
M.(root, path)
node = root
segment path:()
node = node node:(segment)
node
node
M.confidenceRank = {Candidate = , Strong = , Confirmed = }
M.noisyNames = {
[] = , [] = , [] = , [] = ,
[] = , [] = , [] = ,
[] = , [] = , [] = , [] = ,
[] = , [] = , [] = , [] =
}
M.(value)
(value) ~=
value = value:(, ):(, )
value == #value >
M.noisyNames[value:()]
value:() value:()
value
M.(entry, path)
(path) ~= path ==
entry.observedPaths = entry.observedPaths {}
#entry.observedPaths < .(entry.observedPaths, path)
entry.observedPaths[#entry.observedPaths + ] = path
M.(entry, source)
(source) ~= source ==
entry.sources = entry.sources {}
#entry.sources < .(entry.sources, source)
entry.sources[#entry.sources + ] = source
entry.source = .(entry.sources, )
M.(name, options)
name = M.(name)
name
options = options {}
entry = M.observed[name]
entry
entry = {
name = name, displayName = options.displayName name, category = options.category ,
kind = options.kind , icon = M.(options.icon), order = options.order ,
source = , sources = {}, catalog = , filters = options.filters ,
observedPaths = {}, interactions = {}, observedCount = , confidence = options.confidence ,
route = options.route , gunSkin = options.gunSkin, routeHint = options.routeHint,
evidence = options.evidence
}
M.observed[name] = entry
entry.observedCount = (entry.observedCount ) +
options.displayName (entry.displayName == entry.name entry.displayName == ) entry.displayName = options.displayName
options.icon ( entry.icon entry.icon == ) entry.icon = M.(options.icon)
options.kind (entry.kind == options.confidence == ) entry.kind = options.kind
options.route entry.route = options.route
options.gunSkin entry.gunSkin entry.gunSkin = options.gunSkin
options.routeHint entry.routeHint entry.routeHint = options.routeHint
options.evidence entry.evidence entry.evidence = options.evidence
currentRank = M.confidenceRank[entry.confidence]
nextRank = M.confidenceRank[options.confidence]
nextRank > currentRank entry.confidence = options.confidence
M.(entry, options.source )
M.(entry, options.path)
options.interaction
entry.interactions = entry.interactions {}
#entry.interactions < .(entry.interactions, options.interaction) entry.interactions[#entry.interactions + ] = options.interaction
entry
M.()
_, name ({, })
M.(name, {kind = , source = , confidence = , route = , evidence = })
serialized = {
{, }, {, },
{, }, {, },
{, }, {, },
{, }, {, },
{, }, {, }
}
_, pair (serialized)
M.(pair[], {kind = , source = , confidence = , path = pair[]})
worldGiverSeeds = {
, , , , , , , ,
, , , , , , , ,
, , , , , , , ,
, , , , , , ,
, , , , ,
, , , , , ,
, , , , , , , ,
, , , , , , ,
,
}
_, name (worldGiverSeeds)
M.(name, {kind = , source = , confidence = , routeHint = })
toolsContainerSeeds = {
, , , , , ,
, , , ,
}
_, name (toolsContainerSeeds)
M.(name, {kind = , source = , confidence = , routeHint = })
_, name ({
, , ,
, , ,
,
})
M.(name, {kind = , source = , confidence = , routeHint = })
foods = {, , , , , , , }
_, food (foods)
M.( .. food, {kind = , source = , confidence = , routeHint = })
M.( .. food, {kind = , source = , confidence = , routeHint = })
M.(, {kind = , source = , confidence = , routeHint = })
_, name ({
, , ,
, ,
})
M.(name, {kind = , source = , confidence = , routeHint = })
_, name ({, , })
M.(name, {kind = , source = , confidence = , evidence = })
lightningHubKnown = {
, , , , , , , ,
, , , , , , , ,
, , , , , , ,
, , , , , , ,
, , , , , , ,
,
}
_, name (lightningHubKnown)
M.(name, {kind = , source = , confidence = })
M.(root, source, basePath, budget)
(root) ~= ,
seen, found, visited = {}, ,
maxNodes = budget
directKeys = {
tool = , toolname = , toolid = , fulltool = , portiontool = ,
rewardtool = , grantedtool = , equiptool = , backpacktool =
}
(key)
ok, text = (, key)
ok text
(tbl, a, b)
(tbl) ~=
v = (tbl, a)
v == b v = (tbl, b)
v
(node, path, depth)
(node) ~= seen[node] depth > visited >= maxNodes
seen[node] =
key, value = (node)
key ~=
visited = visited +
visited >= maxNodes
keyText = (key)
keyNorm = keyText:(, ):()
childPath = path == keyText (path .. .. keyText)
(value) ==
isToolKey = directKeys[keyNorm] keyNorm:(, , ) keyNorm:(, , )
isToolKey
M.(value, {kind = , source = source, confidence = , path = childPath, evidence = }) found = found +
(value) ==
recordName = (value, , )
recordType = (value, , ) (value, , )
(recordName) == (recordType) == recordType:():(, , )
M.(recordName, {kind = , source = source, confidence = , path = childPath, evidence = }) found = found +
(value, childPath, depth + )
visited % == .()
key, value = (node, key)
(root, basePath , )
found, visited
M.()
specs = {
{path = , label = },
{path = , label = },
{path = , label = },
{path = , label = }
}
total =
_, spec (specs)
module = M.(M.RS, spec.path)
module module:()
ok, result = (, module)
ok (result) ==
found = M.(result, .. spec.label, spec.path, )
total = total + (found )
spec.label == (result.Foods) ==
food (result.Foods)
M.( .. (food), {kind = , source = , confidence = , routeHint = })
M.( .. (food), {kind = , source = , confidence = , routeHint = })
(result.BURNT_FOOD_TOOL) == M.(result.BURNT_FOOD_TOOL, {kind = , source = , confidence = })
spec.label ==
map = result.TOOL_NAME_BY_TYPE
(map) == _, name (map) M.(name, {kind = , source = , confidence = })
(result.ALL_TYPE_NAMES) ==
_, typ (result.ALL_TYPE_NAMES)
M.( .. (typ), {kind = , source = , confidence = })
spec.label == (result.JETTS_MENU_ITEMS_ALL) ==
name, data (result.JETTS_MENU_ITEMS_ALL)
toolName = (data) == data.toolName name
M.(toolName, {kind = , source = , confidence = , routeHint = , icon = (data) == data.image })
spec.label == (result.ADDITIONAL_PROHIBITED_TOOLS) ==
_, name (result.ADDITIONAL_PROHIBITED_TOOLS) M.(name, {kind = , source = , confidence = })
M.(spec.label .. .. (result))
total
M.()
getter = getloadedmodules M.env.getloadedmodules
(getter) ~=
ok, modules = (getter)
ok (modules) ~=
found, checked, skipped = , ,
_, module (modules)
readable, isModule, moduleName, modulePath = (()
module module:(), module module.Name , module module:()
)
readable isModule
lower = (moduleName):()
lower:(, , ) lower:(, , ) lower:(, , ) lower:(, , )
checked +=
success, result = (, module)
success (result) ==
n = M.(result, .. (moduleName), (modulePath), )
found += (n )
skipped +=
readable
skipped +=
checked >=
M.(.(, checked, found, skipped))
found
M.(object)
object ,
current = object
hops =
current current ~= hops <
lower = current.Name:()
lower == lower ==
parent = current.Parent
parent M.(parent.Name), parent:()
parent = current.Parent
parent
plower = parent.Name:()
plower == plower == M.(current.Name), current:()
plower ==
grand = parent.Parent
current:() M.(current.Name), current:()
grand grand.Name M.noisyNames[grand.Name:()] M.(grand.Name), grand:()
current, hops = parent, hops +
,
M.(object)
object
added =
object:()
M.(object, )
object:()
lower = object.Name:(, ):()
lower == lower == lower ==
M.(object.Value, {kind = , source = , confidence = , path = object:()}) added = added +
object:() object:()
name, path = M.(object)
name M.(name, {kind = , source = object.ClassName, confidence = , path = path, routeHint = , interaction = object}) added = added +
object:()
path = object:()
lowerPath = path:()
hasToolMarker = object:() ~=
specialMenu = lowerPath:(, , ) lowerPath:(, , )
hasToolMarker specialMenu
name = M.(object.Name)
lowerName = name name:()
ignored = lowerName == lowerName == lowerName == lowerName == lowerName ==
name ignored lowerName:(, , )
M.(name, {kind = , source = , confidence = , path = path, route = }) added = added +
lname = object.Name:()
lname:(, , ) lname:(, , ) lname:(, , ) lname:(, , ) lname:(, , )
ok, attrs = (object.GetAttributes, object)
ok (attrs) ==
key, value (attrs)
kn = (key):(, ):()
(value) == (kn == kn == kn == kn:(, , ))
M.(value, {kind = , source = , confidence = , path = object:() .. .. (key) .. }) added = added +
added
M.(label, seconds, callback)
result
worker = M.(() result = .((callback)) )
started = .()
result M.dead .() - started < seconds .()
result
worker (.cancel, worker); M.workers[worker] =
M.(label .. )
,
result[] M.(label .. .. (result[]))
.(result, , result.n)
M.()
owned, holdable = {}, {}
roots = {M.Player:(), M.Player.Character, M.Player:()}
index = ,
root = roots[index]
root
_, tool (root:())
tool:()
owned[tool.Name] = tool
index < holdable[tool.Name] = tool
gun = tool:()
gun gun:() gun.Value ~=
owned[gun.Value] = tool
index < holdable[gun.Value] = tool
owned, holdable
M.(name)
_, available = M.()
tool = available[name]
character = M.Player.Character
humanoid = character character:()
tool humanoid humanoid.Health <=
M.( .. name .. , )
tool.Parent ~= character humanoid:(tool)
M.( .. name, )
M.()
re = M.RS:()
remote = re re:()
remote remote:() remote
M.()
list = {}
_, player (M.Players:())
player ~= M.Player list[#list + ] = player
.(list, (a, b) a.Name:() < b.Name:() )
list
M.()
list = M.()
#list ==
M.handoffDonorName =
M.handoffDonorName
_, player (list)
player.Name == M.handoffDonorName player
M.handoffDonorName = list[].Name
list[]
M.()
M.ui M.ui.donor
donor = M.()
donor
M.ui.donor.Text = .. donor.DisplayName .. .. donor.Name ..
M.ui.donor.TextColor3 = M.colors.text
M.ui.donor.Text =
M.ui.donor.TextColor3 = M.colors.bad
M.(step)
list = M.()
#list ==
M.handoffDonorName =
M.()
M.(, )
index =
i, player (list)
player.Name == M.handoffDonorName index = i
index = index + (step )
index > #list index = index < index = #list
M.handoffDonorName = list[index].Name
M.()
M.()
M.( .. list[index].Name, )
list[index]
M.(entry, intent)
M.dead entry entry.isCategory
entry.kind ==
M.(, )
M.busy
M.()
remote = M.()
remote
entry.lastResult =
M.(, )
M.()
donor = M.()
donor
entry.lastResult =
M.(, )
M.()
before = {}
ownedBefore = M.()
name, tool (ownedBefore) before[tool] = name
operation = {name = entry.name, intent = intent , started = .(), route = }
M.busy = operation
M.nextRequest = .() +
entry.lastResult =
M.( .. entry.name .. .. donor.Name .. )
M.( .. entry.name .. .. donor.Name .. )
M.()
M.(()
ok, err = (()
remote:(, entry.name, donor)
)
ok
M.busy == operation M.busy =
entry.lastResult =
M.( .. entry.name .. .. (err))
M.( .. (err):(, ), )
M.()
deadline = .() +
exact, newTool, newName
owned = M.()
exact = owned[entry.name]
exact
name, tool (owned)
before[tool] newTool, newName = tool, name
newTool
.()
M.dead .() >= deadline
M.dead
M.busy == operation M.busy =
M.nextRequest = .() +
exact
entry.lastResult =
M.( .. entry.name .. , )
intent == M.(entry.name)
newTool
entry.lastResult = .. (newName)
M.( .. (newName) .. .. entry.name .. , )
M.( .. entry.name .. .. (newName))
intent == M.(newName)
entry.lastResult =
M.(, )
M.()
)
M.(entry, intent)
interaction
_, candidate (entry.interactions {})
candidate candidate.Parent interaction = candidate
interaction
M.(, )
ok, err
interaction:()
fire = M.env.fireclickdetector
(fire) ~= M.(, );
ok, err = (fire, interaction)
interaction:()
fire = M.env.fireproximityprompt
(fire) ~= M.(, );
ok, err = (fire, interaction)
M.( .. interaction.ClassName, )
ok M.( .. (err):(, ), );
M.( .. entry.name .. )
M.(()
deadline = .() +
found
.()
found = M.()[entry.name]
found M.dead .() >= deadline
M.dead
found
entry.lastResult =
intent == M.(entry.name) M.( .. entry.name .. , )
entry.lastResult =
M.(, )
M.()
)
M.(entry, intent)
M.dead entry
owned = M.()
decision = M.(entry, intent, owned[entry.name] ~= , M.busy ~= )
decision ==
M.category, M.filter, M.page = entry.name, ,
M.()
decision == M.(entry.name);
decision == M.( .. entry.name, );
decision == M.();
decision == M.();
decision == M.(entry, intent);
decision ==
M.( .. entry.name, )
.() < M.nextRequest M.();
path, args = M.(entry)
remote = path M.(M.RS, path)
remote remote:()
entry.interactions #entry.interactions > (intent == intent == )
M.(entry, intent)
M.( .. (path), )
entry.lastResult =
M.()
operation = {name = entry.name, intent = intent, started = .()}
M.busy = operation
M.nextRequest = .() +
M.((intent == ) .. entry.name .. )
M.( .. intent .. .. entry.name .. .. path)
M.()
M.(()
ok, response = (() remote:(.(args)) )
M.dead
M.( .. entry.name .. .. (ok (response) ( .. (response))))
deadline = .() +
found = M.()[entry.name]
.() < deadline M.dead
found = M.()[entry.name]
(intent == found) (intent ~= found)
ok
.()
M.dead
M.busy =
M.nextRequest = .() +
intent == found
entry.lastResult =
M.( .. entry.name, )
intent ~= found
entry.lastResult =
intent == M.(entry.name) M.( .. entry.name, )
ok
entry.lastResult =
entry.interactions #entry.interactions > (intent == intent == )
M.( .. entry.name .. )
M.()
.()
M.(entry, intent)
M.( .. (response):(, ), )
response ==
entry.lastResult =
entry.interactions #entry.interactions > (intent == intent == )
M.( .. entry.name .. )
M.()
.()
M.(entry, intent)
M.(entry.name .. , )
intent ~=
response ~= entry.interactions #entry.interactions >
entry.lastResult =
M.( .. entry.name .. )
M.()
.()
M.(entry, intent)
entry.lastResult = response ==
M.( .. entry.name .. , response == )
entry.lastResult =
M.( .. (response), )
M.()
)
M.()
previous = M.byName {}
merged = {}
(entry)
copy = {}
key, value (entry)
(value) == (key == key == key == )
t = {}
i, item (value) t[i] = item
copy[key] = t
copy[key] = value
copy
name, entry (M.catalog)
copy = (entry)
previous[name] copy.lastResult = previous[name].lastResult
copy.sources = {entry.source}
copy.route = copy.route ( copy.isCategory )
merged[name] = copy
name, observation (M.observed)
merged[name]
target = merged[name]
_, path (observation.observedPaths {}) M.(target, path)
_, source (observation.sources {}) M.(target, source)
observation.interactions
target.interactions = target.interactions {}
_, interaction (observation.interactions)
#target.interactions < .(target.interactions, interaction) target.interactions[#target.interactions + ] = interaction
observation.evidence target.evidence target.evidence = observation.evidence
copy = (observation)
previous[name] copy.lastResult = previous[name].lastResult
copy.route = copy.route
copy.kind = copy.kind
copy.category = copy.category
merged[name] = copy
M.entries = {}
_, entry (merged)
entry.categoryPath = M.(entry, M.categories)
M.entries[#M.entries + ] = entry
.(M.entries, (a, b)
aCategory = a.isCategory ==
bCategory = b.isCategory ==
aCategory ~= bCategory aCategory
aCatalog = a.catalog ==
bCatalog = b.catalog ==
aCatalog ~= bCatalog aCatalog
aOrder = (a.order)
bOrder = (b.order)
aOrder ~= bOrder aOrder < bOrder
aName = (a.name ):()
bName = (b.name ):()
aName ~= bName aName < bName
)
M.byName = merged
okRender, renderErr = (M.render, )
okRender M.( .. (renderErr))
M.(tool, source)
tool:() tool.Name ==
entry = M.(tool.Name, {displayName = tool.Name, kind = , icon = tool.TextureId,
source = source , confidence = , path = tool:()})
entry
gun = tool:()
gun gun:() gun.Value ~=
M.(gun.Value, {displayName = gun.Value, kind = , source = source ,
confidence = , path = tool:() .. , routeHint = })
M.()
M.scanning M.dead
M.scanning =
M.ui.scan.Text =
M.()
M.(()
ok, err = (()
checked, found = ,
roots = {M.RS, , M.Players, :(), :(), M.PlayerGui}
seenRoots = {}
_, root (roots)
root seenRoots[root]
seenRoots[root] =
found = found + M.(root)
_, object (root:())
M.dead
checked = checked +
found = found + M.(object)
checked % == .()
tagsOk, tags = (() M.Tags:() )
tagsOk (tags) ==
_, tag (tags)
lower = (tag):()
lower:(, , ) lower:(, , ) lower:(, , ) lower:(, , )
_, object (M.Tags:(tag))
object:() M.(object, .. tag); found = found +
ancestor = object:()
ancestor M.(ancestor, .. tag); found = found +
found = found + (M.() )
found = found + (M.() )
M.deepStats.lastChecked, M.deepStats.lastHits = checked, found
M.(.(, checked, found))
)
M.dead
M.scanning =
M.ui.scan.Text =
ok M.( .. (err))
M.()
M.mining M.busy M.(, ok)
)
M.()
result, seenRoots = {}, {}
ignore = {Template=, ClearTools=, BackButton=, Delete=, GreenCheckMark=, Search=, Close=}
(button, source)
button:() ignore[button.Name]
name = M.(button.Name)
name
path = button:()
looksTool = button:() ~= path:():(, , )
path:():(, , ) path:():(, , )
looksTool
icon = button:()
image = icon (icon:() icon:()) icon.Image
result[name] = result[name] {name=name, displayName=name, category=, icon=image, order=button.LayoutOrder,
kind=, source=source, sources={source}, catalog=, filters=, observedPaths={path}, route=}
(root, source)
root seenRoots[root]
seenRoots[root] =
_, obj (root:())
obj:() (obj, source)
_, root (M.Tags:()) (root, )
_, root (M.Tags:()) (root, )
starterGui = :()
_, root ({M.PlayerGui, starterGui})
root
_, obj (root:())
obj.Name == obj.Name == (obj, )
result
M.(generation)
module = M.(M.RS, )
db
module module:()
ok, result = (, module)
ok (result) ==
db = result
(db.cache) == db.cache, ,
remote = M.RS:()
remote remote:()
success, packages, defaultPackage = M.(, , () remote:() )
success (packages) ==
M.remoteTree = packages
config, packageName = M.(packages, defaultPackage)
(config) == config, .. (packageName), packages
M.dead M.generation ~= generation , , ,
module db
(()
controllerModule = M.(M.RS, )
controllerModule controllerModule:()
controller = (controllerModule)
(controller) == (controller.LoadDatabase) == controller.(module)
)
deadline = .() +
.() < deadline M.dead M.generation == generation
(db.cache) == db.cache, , M.remoteTree
.()
(db.GetConfig) ==
success, config = M.(, , () db.() )
success (config) == config, , M.remoteTree
, , M.remoteTree,
M.()
M.mining M.dead
M.mining =
M.generation +=
generation = M.generation
M.ui.refresh.Text =
M.()
M.(()
ok, errorMessage = (()
M.observed = {}
M.()
config, source, packages, configError = M.(generation)
M.dead M.generation ~= generation
config
entries, categories, stats = M.(config, source)
M.catalog, M.categories, M.rawConfig, M.stats = entries, categories, config, stats
M.source = source
M.(.(, stats.tools, stats.categories, stats.rows))
M.catalog, M.categories, M.rawConfig = {}, {},
M.source =
M.( .. (configError))
(packages) ==
deepHits, visited = M.(packages, , , )
M.(.(, deepHits , visited ))
M.()
M.()
uiRows, uiCount = M.(),
name, entry (uiRows)
uiCount +=
M.(name, {displayName=entry.displayName, kind=entry.kind, icon=entry.icon, source=entry.source,
confidence=, route=, path=entry.observedPaths entry.observedPaths[]})
M.( .. (uiCount))
M.()
nativeCount, extraCount = ,
_, entry (M.entries)
entry.isCategory
entry.catalog nativeCount += extraCount +=
M.coverage = .(, nativeCount, extraCount, nativeCount + extraCount)
M.(.(, nativeCount + extraCount), )
, debug.traceback)
M.dead
M.mining =
ok
M.trace("Mining stage error: " .. tostring(errorMessage))
M.status("Mining stage hit a protected object/module; continuing with the catalog already recovered.", false)
end
if M.ui and M.ui.refresh then pcall(function() M.ui.refresh.Text = "Re-mine all" end) end
M.scanWorld()
end)
end
function M.export(mode)
if mode == "log" then return table.concat(M.logs, "\n") end
local entries = M.entries
if mode == "names" then
local lines = {}
for _, e in ipairs(entries) do if not e.isCategory then lines[#lines + 1] = e.name end end
return table.concat(lines, "\n")
end
if mode == "json" then
local items = {}
for _, e in ipairs(entries) do
items[#items + 1] = {name=e.name, displayName=e.displayName, kind=e.kind, category=e.category,
categoryPath=e.categoryPath, source=e.source, route=e.route, gunSkin=e.gunSkin, item=e.item,
filters=e.filters, requirement=e.requirement, hiddenUnlessUnlocked=e.hiddenUnlessUnlocked,
sources=e.sources, evidence=e.evidence, observedPaths=e.observedPaths, lastResult=e.lastResult, raw=e.raw}
end
local ok, json = pcall(function()
return M.Http:JSONEncode({minerVersion=M.version, placeId=game.PlaceId, source=M.source, coverage=M.coverage,
exportedAtUtc=os.date("!%Y-%m-%dT%H:%M:%SZ"), entries=items})
end)
return ok and json or ("JSON export failed: " .. tostring(json))
end
local lines = {"Tool Miner " .. M.version, "Source: " .. M.source, "Coverage: " .. M.coverage,
"Every non-category row has an actionable native request route; server unlock checks still apply.", "",
"Name\tKind\tCategory\tDisplay name\tRoute\tLast result\tSource\tItem / requirement"}
local function clean(s) return tostring(s or ""):gsub("[\t\r\n]", " ") end
for _, e in ipairs(entries) do
lines[#lines + 1] = table.concat({clean(e.name), clean(e.kind), clean(e.categoryPath), clean(e.displayName),
clean(e.route or ""), clean(e.lastResult or "UNTESTED"), clean(e.source), clean((e.item or "") .. " " .. (e.requirement or ""))}, "\t")
end
return table.concat(lines, "\n")
end
function M.new(class, parent, properties)
local object = Instance.new(class)
for key, value in pairs(properties or {}) do object[key] = value end
object.Parent = parent
return object
end
function M.round(object, radius)
M.new("UICorner", object, {CornerRadius = UDim.new(0, radius or 6)})
end
function M.label(parent, text, pos, size, textSize, color)
return M.new("TextLabel", parent, {BackgroundTransparency = 1, Text = text, Position = pos, Size = size,
Font = Enum.Font.Gotham, TextSize = textSize or 12, TextColor3 = color or M.colors.text,
TextXAlignment = Enum.TextXAlignment.Left, TextTruncate = Enum.TextTruncate.AtEnd})
end
function M.button(parent, text, pos, size, callback, bucket)
local button = M.new("TextButton", parent, {Text = text, Position = pos, Size = size, BorderSizePixel = 0,
BackgroundColor3 = M.colors.row, TextColor3 = M.colors.text, Font = Enum.Font.GothamMedium,
TextSize = 12, AutoButtonColor = true})
M.round(button)
if callback then M.track(button.Activated:Connect(callback), bucket) end
return button
end
function M.showExport(mode)
M.modalMode = mode
M.ui.exportTitle.Text = mode == "log" and "Tool Miner log" or "Export all discoveries"
M.ui.exportBox.Text = M.export(mode)
M.ui.modal.Visible = true
for name, button in pairs(M.ui.exportModes) do button.BackgroundColor3 = name == mode and M.colors.active or M.colors.row end
end
function M.copy()
local copier = setclipboard or M.env.setclipboard
if type(copier) == "function" then
local ok = pcall(copier, M.ui.exportBox.Text)
if ok then M.ui.copy.Text = "Copied"; return end
end
M.ui.exportBox:CaptureFocus()
M.ui.exportBox.CursorPosition = #M.ui.exportBox.Text + 1
M.ui.exportBox.SelectionStart = 1
M.ui.copy.Text = "Press Ctrl+C"
end
function M.details()
if not M.ui or M.dead then return end
local entry = M.selected and M.byName and M.byName[M.selected]
if not entry then
M.ui.detailTitle.Text = "Select a tool"
M.ui.detailImage.Image = ""
M.ui.detailText.Text = "v5 adds Brookhaven's real player-to-player tool handoff route from the supplied place.\n\nPick a donor (Client2 works), select any normal tool, then use Handoff receive. This sends the same recipient acceptance action the stock client uses after another player offers a tool."
M.ui.get.Visible, M.ui.hold.Visible, M.ui.handoff.Visible, M.ui.remove.Visible = false, false, false, false
return
end
local owned, usable = M.inventory()
local state = owned[entry.name] and (usable[entry.name] and "In inventory" or "In StarterGear") or "Not in inventory"
local lines = {entry.name, "", "Type: " .. tostring(entry.kind or "Tool"),
"Category: " .. (entry.categoryPath or "General"), "Source: " .. tostring(entry.source or "Unknown"),
"Inventory: " .. state, "Route: " .. tostring(entry.route or "PickingTools"),
"Last request: " .. tostring(entry.lastResult or "UNTESTED"),
"Handoff donor: " .. tostring((M.resolveDonor() and M.resolveDonor().Name) or "none")}
if entry.gunSkin then lines[#lines + 1] = "Base gun: " .. tostring(entry.gunSkin) end
if entry.item then lines[#lines + 1] = "Linked item: " .. tostring(entry.item) end
if entry.filters and entry.filters ~= "" then lines[#lines + 1] = "Menu filters: " .. entry.filters end
if entry.requirement and entry.requirement ~= "" then lines[#lines + 1] = "Requirement: " .. entry.requirement end
if entry.hiddenUnlessUnlocked then lines[#lines + 1] = "Native menu hides this until unlocked." end
if entry.evidence then lines[#lines + 1] = "Evidence: " .. entry.evidence end
if entry.sources and #entry.sources > 1 then
lines[#lines + 1] = "\nFound by:"
for _, source in ipairs(entry.sources) do lines[#lines + 1] = "- " .. source end
end
if entry.observedPaths and #entry.observedPaths > 0 then
lines[#lines + 1] = "\nObserved paths:"
for _, path in ipairs(entry.observedPaths) do lines[#lines + 1] = path end
end
if entry.interactions and #entry.interactions > 0 then
lines[#lines + 1] = "\nLoaded native giver/prompt fallback: YES"
end
M.ui.detailTitle.Text = entry.displayName or entry.name
M.ui.detailImage.Image = entry.icon or ""
M.ui.detailText.Text = table.concat(lines, "\n")
M.ui.get.Visible = true
M.ui.hold.Visible = not entry.isCategory
M.ui.handoff.Visible = not entry.isCategory and entry.kind ~= "Gun skin"
M.ui.remove.Visible = not entry.isCategory and owned[entry.name] ~= nil
M.ui.get.Text = entry.isCategory and "Open category" or (owned[entry.name] and "Already owned" or "Get tool")
if M.busy and M.busy.name == entry.name then M.ui.get.Text = "Pending..." end
end
function M.render(resetScroll)
if not M.ui or M.dead then return end
local owned, matched = M.inventory(), {}
local nativeCount, extraCount, categoryCount, testedCount = 0, 0, 0, 0
for _, entry in ipairs(M.entries) do
if entry.isCategory then categoryCount += 1
elseif entry.catalog then nativeCount += 1
else extraCount += 1 end
if not entry.isCategory and entry.lastResult then testedCount += 1 end
local include = not entry.isCategory
if M.filter == "Native config" then include = entry.catalog and not entry.isCategory
elseif M.filter == "Extra mined" then include = not entry.catalog and not entry.isCategory
elseif M.filter == "Gun skins" then include = entry.kind == "Gun skin"
elseif M.filter == "Categories" then include = entry.isCategory
elseif M.filter == "In bag" then include = owned[entry.name] ~= nil end
if include and M.inCategory(entry, M.category, M.categories) and M.matches(entry, M.query) then matched[#matched + 1] = entry end
end
M.filtered = matched
local pages = math.max(1, math.ceil(#matched / M.pageSize))
M.page = math.clamp(M.page, 1, pages)
M.ui.subtitle.Text = string.format("%d tools total / %d native / %d extra mined / %d tested | %s", nativeCount + extraCount, nativeCount, extraCount, testedCount, M.coverage)
M.ui.category.Text = M.category ~= "" and ("Category: " .. M.category .. " [clear]") or "Category: All / select Categories to browse"
M.ui.pages.Text = string.format("%d results | %d / %d", #matched, M.page, pages)
for name, button in pairs(M.ui.tabs) do button.BackgroundColor3 = name == M.filter and M.colors.active or M.colors.row end
M.disconnect(M.rows)
for _, child in ipairs(M.ui.list:GetChildren()) do if child:IsA("GuiObject") then child:Destroy() end end
local first = (M.page - 1) * M.pageSize + 1
for index = first, math.min(#matched, first + M.pageSize - 1) do
local entry = matched[index]
local row = M.button(M.ui.list, "", UDim2.fromOffset(0, 0), UDim2.new(1, -8, 0, 61), function()
M.selected = entry.name
M.render(false)
end, M.rows)
row.LayoutOrder = index
row.BackgroundColor3 = M.selected == entry.name and M.colors.active or M.colors.row
M.new("ImageLabel", row, {BackgroundTransparency=1, Size=UDim2.fromOffset(45,45), Position=UDim2.fromOffset(8,8), Image=entry.icon or "", ScaleType=Enum.ScaleType.Fit})
local title = M.label(row, entry.displayName or entry.name, UDim2.fromOffset(64,9), UDim2.new(1,-138,0,20), 13)
title.Font = Enum.Font.GothamMedium
M.label(row, entry.name .. " / " .. (entry.categoryPath or entry.kind or "Tool"), UDim2.fromOffset(64,33), UDim2.new(1,-80,0,16), 10, M.colors.muted)
local badge
if owned[entry.name] then badge = "IN BAG"
elseif entry.isCategory then badge = "FOLDER"
elseif entry.lastResult then badge = entry.lastResult
elseif entry.catalog then badge = "NATIVE"
else badge = "EXTRA" end
M.label(row, badge, UDim2.new(1,-86,0,12), UDim2.fromOffset(80,18), 9, owned[entry.name] and M.colors.good or M.colors.accent)
end
M.ui.empty.Visible = #matched == 0
M.ui.empty.Text = #M.entries == 0 and "Mining the complete tool union...\nOpen Log if loading fails." or "No results for this filter."
if resetScroll then M.ui.list.CanvasPosition = Vector2.new(0, 0) end
M.details()
end
function M.unload()
if M.dead then return end
M.dead = true
M.generation = M.generation + 1
M.disconnect(M.connections)
M.disconnect(M.rows)
local current = coroutine.running()
for thread in pairs(M.workers) do if thread ~= current then pcall(task.cancel, thread) end end
table.clear(M.workers)
if M.gui then M.gui:Destroy() end
if M.env.ToolMinerSpawnerUnload == M.unload then M.env.ToolMinerSpawnerUnload = nil end
end
function M.buildUI()
M.gui = M.new("ScreenGui", nil, {Name = "ToolMinerSpawner", ResetOnSpawn = false,
IgnoreGuiInset = true, DisplayOrder = 100, ZIndexBehavior = Enum.ZIndexBehavior.Sibling})
-- Keep the UI under PlayerGui. Some runtimes let the startup thread parent into
-- gethui/CoreGui but later worker threads cannot touch those Instances and throw
-- "lacking capability Plugin". PlayerGui avoids that capability split entirely.
local parented = pcall(function() M.gui.Parent = M.PlayerGui end)
if not parented then error("Tool Miner could not create its PlayerGui interface.") end
local U = {}
M.ui = U
U.main = M.new("Frame", M.gui, {Size = UDim2.fromOffset(920, 650), AnchorPoint = Vector2.new(0.5, 0.5),
Position = UDim2.fromScale(0.5, 0.5), BackgroundColor3 = M.colors.bg, BorderSizePixel = 0})
M.round(U.main, 10)
M.new("UIStroke", U.main, {Color = M.colors.line, Thickness = 1})
U.scale = M.new("UIScale", U.main, {Scale = 1})
U.header = M.new("Frame", U.main, {Size = UDim2.new(1, 0, 0, 63), BackgroundTransparency = 1, Active = true})
local title = M.label(U.header, "Tool Miner v5.1 - Player Handoff", UDim2.fromOffset(16, 10), UDim2.fromOffset(205, 24), 20)
title.Font = Enum.Font.GothamBold
U.subtitle = M.label(U.header, "Reading the live catalog...", UDim2.fromOffset(16, 39), UDim2.new(1, -30, 0, 18), 10, M.colors.muted)
U.refresh = M.button(U.header, "Re-mine all", UDim2.fromOffset(426, 9), UDim2.fromOffset(83, 28), M.mine)
U.scan = M.button(U.header, "Deep scan", UDim2.fromOffset(515, 9), UDim2.fromOffset(91, 28), M.scanWorld)
M.button(U.header, "Export", UDim2.fromOffset(612, 9), UDim2.fromOffset(72, 28), function() M.showExport("report") end)
M.button(U.header, "Log", UDim2.fromOffset(690, 9), UDim2.fromOffset(57, 28), function() M.showExport("log") end)
M.button(U.header, "Hide", UDim2.fromOffset(753, 9), UDim2.fromOffset(60, 28), function() U.main.Visible = false end)
M.button(U.header, "X", UDim2.fromOffset(866, 9), UDim2.fromOffset(36, 28), M.unload)
U.search = M.new("TextBox", U.main, {Position = UDim2.fromOffset(16, 72), Size = UDim2.new(1, -32, 0, 34),
BackgroundColor3 = M.colors.panel, BorderSizePixel = 0, Text = "", PlaceholderText = "Search every mined tool name, source, category, event item...",
PlaceholderColor3 = M.colors.muted, TextColor3 = M.colors.text, Font = Enum.Font.Gotham, TextSize = 13,
ClearTextOnFocus = false, TextXAlignment = Enum.TextXAlignment.Left})
M.round(U.search)
M.new("UIPadding", U.search, {PaddingLeft = UDim.new(0, 10), PaddingRight = UDim.new(0, 10)})
U.tabs = {}
for index, name in ipairs({"All tools", "Native config", "Extra mined", "Gun skins", "Categories", "In bag"}) do
U.tabs[name] = M.button(U.main, name, UDim2.fromOffset(16 + (index - 1) * 148, 116), UDim2.fromOffset(140, 29), function()
M.filter, M.page = name, 1
M.render(true)
end)
end
U.category = M.button(U.main, "Category: All", UDim2.fromOffset(16, 153), UDim2.fromOffset(554, 25), function()
M.category, M.page = "", 1
M.render(true)
end)
U.list = M.new("ScrollingFrame", U.main, {Position = UDim2.fromOffset(16, 187), Size = UDim2.fromOffset(554, 385),
BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 4, ScrollBarImageColor3 = M.colors.accent,
CanvasSize = UDim2.fromOffset(0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y})
M.new("UIListLayout", U.list, {Padding = UDim.new(0, 5), SortOrder = Enum.SortOrder.LayoutOrder})
U.empty = M.label(U.main, "", UDim2.fromOffset(42, 255), UDim2.fromOffset(480, 80), 13, M.colors.muted)
U.empty.TextWrapped = true
U.pages = M.label(U.main, "", UDim2.fromOffset(17, 584), UDim2.fromOffset(300, 24), 11, M.colors.muted)
M.button(U.main, "Previous", UDim2.fromOffset(383, 580), UDim2.fromOffset(88, 29), function()
M.page = M.page - 1; M.render(true)
end)
M.button(U.main, "Next", UDim2.fromOffset(479, 580), UDim2.fromOffset(88, 29), function()
M.page = M.page + 1; M.render(true)
end)
U.detail = M.new("Frame", U.main, {Position = UDim2.fromOffset(585, 153), Size = UDim2.fromOffset(319, 456),
BackgroundColor3 = M.colors.panel, BorderSizePixel = 0})
M.round(U.detail)
U.detailImage = M.new("ImageLabel", U.detail, {Position = UDim2.fromOffset(13, 12), Size = UDim2.fromOffset(52, 52),
BackgroundTransparency = 1, Image = "", ScaleType = Enum.ScaleType.Fit})
U.detailTitle = M.label(U.detail, "Select a tool", UDim2.fromOffset(76, 16), UDim2.fromOffset(229, 40), 15)
U.detailTitle.TextWrapped = true
U.detailTitle.Font = Enum.Font.GothamBold
U.donor = M.button(U.detail, "Donor: scanning...", UDim2.fromOffset(13, 72), UDim2.fromOffset(292, 25), function()
M.cycleDonor(1)
end)
U.donor.TextSize = 10
U.donor.TextXAlignment = Enum.TextXAlignment.Left
M.new("UIPadding", U.donor, {PaddingLeft = UDim.new(0, 8), PaddingRight = UDim.new(0, 8)})
local scroll = M.new("ScrollingFrame", U.detail, {Position = UDim2.fromOffset(13, 105), Size = UDim2.fromOffset(295, 255),
BackgroundTransparency = 1, BorderSizePixel = 0, CanvasSize = UDim2.fromOffset(0, 0),
AutomaticCanvasSize = Enum.AutomaticSize.Y, ScrollBarThickness = 3})
U.detailText = M.label(scroll, "", UDim2.fromOffset(0, 0), UDim2.new(1, -9, 0, 0), 12, M.colors.muted)
U.detailText.AutomaticSize = Enum.AutomaticSize.Y
U.detailText.TextWrapped = true
U.detailText.TextYAlignment = Enum.TextYAlignment.Top
U.detailText.TextTruncate = Enum.TextTruncate.None
U.get = M.button(U.detail, "Get tool", UDim2.fromOffset(13, 377), UDim2.fromOffset(142, 30), function()
M.act(M.byName and M.byName[M.selected], "get")
end)
U.get.BackgroundColor3 = M.colors.active
U.hold = M.button(U.detail, "Hold", UDim2.fromOffset(163, 377), UDim2.fromOffset(142, 30), function()
M.act(M.byName and M.byName[M.selected], "hold")
end)
U.handoff = M.button(U.detail, "Handoff receive", UDim2.fromOffset(13, 414), UDim2.fromOffset(142, 28), function()
M.handoff(M.byName and M.byName[M.selected], "get")
end)
U.handoff.BackgroundColor3 = M.colors.active
U.remove = M.button(U.detail, "Remove", UDim2.fromOffset(163, 414), UDim2.fromOffset(142, 28), function()
M.act(M.byName and M.byName[M.selected], "remove")
end)
U.remove.TextColor3 = M.colors.bad
U.status = M.label(U.main, "", UDim2.fromOffset(16, 617), UDim2.new(1, -32, 0, 23), 11, M.colors.muted)
U.modal = M.new("Frame", U.main, {Size = UDim2.fromScale(1, 1), BackgroundColor3 = M.colors.bg,
BorderSizePixel = 0, Visible = false, ZIndex = 20, Active = true})
M.round(U.modal, 10)
U.exportTitle = M.label(U.modal, "Export all discoveries", UDim2.fromOffset(16, 13), UDim2.fromOffset(600, 30), 18)
M.button(U.modal, "Back", UDim2.new(1, -98, 0, 13), UDim2.fromOffset(80, 30), function()
U.modal.Visible = false; M.modalMode = nil
end)
U.exportModes = {}
for index, item in ipairs({{"names", "Names"}, {"report", "Full report"}, {"json", "JSON + raw config"}, {"log", "Log"}}) do
U.exportModes[item[1]] = M.button(U.modal, item[2], UDim2.fromOffset(16 + (index - 1) * 170, 56), UDim2.fromOffset(161, 30), function()
U.copy.Text = "Copy"; M.showExport(item[1])
end)
end
U.copy = M.button(U.modal, "Copy", UDim2.new(1, -123, 0, 56), UDim2.fromOffset(107, 30), M.copy)
local exportScroll = M.new("ScrollingFrame", U.modal, {Position = UDim2.fromOffset(16, 99), Size = UDim2.new(1, -32, 1, -139),
BackgroundColor3 = M.colors.panel, BorderSizePixel = 0, CanvasSize = UDim2.fromOffset(0, 0),
AutomaticCanvasSize = Enum.AutomaticSize.Y, ScrollBarThickness = 5})
U.exportBox = M.new("TextBox", exportScroll, {Position = UDim2.fromOffset(8, 8), Size = UDim2.new(1, -21, 0, 32),
AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, Text = "", MultiLine = true,
ClearTextOnFocus = false, TextEditable = false, TextWrapped = true, Font = Enum.Font.Code, TextSize = 12,
TextColor3 = M.colors.text, TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Top})
M.label(U.modal, "Exports include the full spawn union and each tool's last request result. Server unlock checks still apply.", UDim2.fromOffset(16, 617), UDim2.new(1, -32, 0, 22), 11, M.colors.muted)
M.track(U.search:GetPropertyChangedSignal("Text"):Connect(function()
M.query, M.page = U.search.Text, 1
M.render(true)
end))
M.track(M.Input.InputBegan:Connect(function(input, processed)
if input.KeyCode == Enum.KeyCode.RightShift and not processed and not M.Input:GetFocusedTextBox() then
U.main.Visible = not U.main.Visible
end
end))
local drag
M.track(U.header.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch then
drag = {input = input, start = input.Position, position = U.main.Position}
end
end))
M.track(M.Input.InputChanged:Connect(function(input)
if drag and (input.UserInputType == Enum.UserInputType.MouseMovement or input == drag.input) then
local delta = input.Position - drag.start
U.main.Position = UDim2.new(drag.position.X.Scale, drag.position.X.Offset + delta.X,
drag.position.Y.Scale, drag.position.Y.Offset + delta.Y)
end
end))
M.track(M.Input.InputEnded:Connect(function(input)
if drag and (input == drag.input or input.UserInputType == Enum.UserInputType.MouseButton1) then drag = nil end
end))
local function resize()
local camera = workspace.CurrentCamera
if camera then U.scale.Scale = math.clamp(math.min((camera.ViewportSize.X - 24) / 920, (camera.ViewportSize.Y - 24) / 650), 0.25, 1) end
end
local cameraConnection
local function bindCamera()
if cameraConnection then cameraConnection:Disconnect() end
if workspace.CurrentCamera then cameraConnection = M.track(workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(resize)) end
resize()
end
M.track(workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(bindCamera))
bindCamera()
end
M.buildUI()
M.env.ToolMinerSpawnerUnload = M.unload
M.refreshDonorButton()
-- Log real incoming tool offers so the exact stock payload can be compared with the handoff probe.
do
local handoffRemote = M.playerTrigRemote()
if handoffRemote then
M.track(handoffRemote.OnClientEvent:Connect(function(action, donor, icon, toolName)
if action == "ToolGiveToClient" then
M.lastIncomingOffer = {donor = donor, icon = icon, toolName = toolName, at = os.clock()}
local donorName = typeof(donor) == "Instance" and donor.Name or tostring(donor)
M.trace("Incoming native tool offer: donor=" .. donorName .. " tool=" .. tostring(toolName) .. " icon=" .. tostring(icon))
if typeof(donor) == "Instance" and donor:IsA("Player") then
M.handoffDonorName = donor.Name
M.refreshDonorButton()
end
end
end))
else
M.trace("Player handoff remote missing at startup: RE.1Playe1rTrigge1rEven1t")
end
end
M.track(M.Players.PlayerAdded:Connect(function() task.defer(M.refreshDonorButton) end))
M.track(M.Players.PlayerRemoving:Connect(function(player)
if M.handoffDonorName == player.Name then M.handoffDonorName = nil end
task.defer(M.refreshDonorButton)
end))
M.render(true)
M.trace("Tool Miner v" .. M.version .. " started. PlaceId=" .. tostring(game.PlaceId))
M.trace("Capability fix active: PlayerGui-only UI + direct task.spawn workers + protected-module skips.")
M.trace("Deep-scan fix active: raw table traversal avoids metatable Signal traps; stable normalized sorter enabled.")
M.trace("Spawn Union layers: ToolsConfig + RemoteConfig tree + native UI + visible Tool instances + ToolGivers + dynamic configs + place-derived families + LightningHub-known names.")
M.trace("Player handoff route: AcceptedToolToServer(toolName, donorPlayer) via RE.1Playe1rTrigge1rEven1t.")
M.trace("Every normal tool can also be tested through Handoff receive using a real other player as donor identity.")
-- Inventory changes update visible state; one small poll also catches GunName changes.
M.spawn(function()
local previous = ""
while not M.dead do
local owned = M.inventory()
local names = {}
for name in pairs(owned) do names[#names + 1] = name end
table.sort(names)
local signature = table.concat(names, "\n")
if signature ~= previous then
previous = signature
for _, tool in pairs(owned) do M.observe(tool, "Your inventory") end
M.merge()
end
task.wait(0.7)
end
end)
-- Catch tools that stream/spawn after the initial deep scan without rescanning the whole place.
local function watchRoot(root)
if not root then return end
M.track(root.DescendantAdded:Connect(function(object)
if M.dead then return end
if object:IsA("Tool") then
M.observe(object, "Spawned/streamed live")
M.merge()
elseif object:IsA("StringValue") then
local lower = object.Name:gsub("[^%w]", ""):lower()
if lower == "toolname" or lower == "toolid" then
M.inspectDiscoveryObject(object)
M.merge()
end
end
end))
end
watchRoot(workspace)
watchRoot(M.RS)
watchRoot(M.PlayerGui)
M.mine()this is an unfinished project its open source for a reason dont flame in comments lol if you dont like it finish it yourself..

Universal