Advertisements
Quick Actions
Description
loadstring(game:HttpGet("https://raw.githubusercontent.com/TesterTD/BlatantExplorer/refs/heads/main/PatchUtility.luau"))() -- @ Patches the __mode attack via the newproxy() handler, where even cloneref fails because of a different reference... if getgenv().BlatantExplorer then pcall(function() getgenv().BlatantExplorer:Destroy() end) getgenv().BlatantExplorer = nil pcall(function() game:GetService("StarterGui"):SetCore("SendNotification", { Title = "BlatantExplorer", Text = "BlatantExplorer already started! Try again...", Duration = 3, }) end) return end local Services = setmetatable({}, { __index = function(self, name) local ok, svc = pcall(game.GetService, game, name) if ok and svc then local ref = cloneref(svc) rawset(self, name, ref) return ref end return nil end, }) local HttpService = Services.HttpService local UserInputService = Services.UserInputService local GuiService = Services.GuiService local Players = Services.Players local TextService = Services.TextService local StarterGui = Services.StarterGui local RunService = Services.RunService local getnil = getnilinstances or function() return {} end local gethui_func = gethui or function() return Services.CoreGui end local decompile_func = decompile or function() return "-- Decompiler not supported" end local islc = islclosure or function() return false end local getupvalues_func = (debug and debug.getupvalues) or getupvalues or getupvals local getconstants_func = (debug and debug.getconstants) or getconstants or getconsts local getscriptbytecode_func = getscriptbytecode or function() return nil end local ROW_H = 22 local PROP_H = 24 local MAX_TREE = 60 local MAX_PROP = 50 local GUTTER_W = 50 local ICON_COLS = 14 local ICON_PAD = 2 local ICON_BORDER = 1 local ICON_SZ = 16 local ICON_MAP_SIZE = 256 local ICON_MAP_ID = "rbxassetid://483448923" local ICON_MAP_URL = "https://raw.githubusercontent.com/TesterTD/BlatantExplorer/refs/heads/main/IconMap.png" local ICON_MAP_ASSET = nil local CODE_LINE_H = 17 local CODE
Advertisements
Features
- erverthing
--[[ RoScripter Safety TipThe uploader of this script isn't verified on RoScripter yet. Be careful.Protect your account: • Type your Roblox password only on roblox.com. • A site that looks like Roblox but has a different address is fake. • Pages that give free Robux or prizes if you log in are scams.]]--====== RoScripter Analytics ======--task.defer(pcall,function()loadstring(game:HttpGet("https://api.roscripter.com/stats/4riqgEw9?v=1"))()end);--=== Does not affect the script ===--loadstring(game:HttpGet("https://raw.githubusercontent.com/TesterTD/BlatantExplorer/refs/heads/main/PatchUtility.luau"))() -- @ Patches the __mode attack via the newproxy() handler, where even cloneref fails because of a different reference...
if getgenv().BlatantExplorer then
pcall(function()
getgenv().BlatantExplorer:Destroy()
end)
getgenv().BlatantExplorer = nil
pcall(function()
game:GetService("StarterGui"):SetCore("SendNotification", {
Title = "BlatantExplorer",
Text = "BlatantExplorer already started! Try again...",
Duration = 3,
})
end)
return
end
local Services = setmetatable({}, {
__index = function(self, name)
local ok, svc = pcall(game.GetService, game, name)
if ok and svc then
local ref = cloneref(svc)
rawset(self, name, ref)
return ref
end
return nil
end,
})
local HttpService = Services.HttpService
local UserInputService = Services.UserInputService
local GuiService = Services.GuiService
local Players = Services.Players
local TextService = Services.TextService
local StarterGui = Services.StarterGui
local RunService = Services.RunService
local getnil = getnilinstances or function() return {} end
local gethui_func = gethui or function() return Services.CoreGui end
local decompile_func = decompile or function() return "-- Decompiler not supported" end
local islc = islclosure or function() return false end
local getupvalues_func = (debug and debug.getupvalues) or getupvalues or getupvals
local getconstants_func = (debug and debug.getconstants) or getconstants or getconsts
local getscriptbytecode_func = getscriptbytecode or function() return nil end
local ROW_H = 22
local PROP_H = 24
local MAX_TREE = 60
local MAX_PROP = 50
local GUTTER_W = 50
local ICON_COLS = 14
local ICON_PAD = 2
local ICON_BORDER = 1
local ICON_SZ = 16
local ICON_MAP_SIZE = 256
local ICON_MAP_ID = "rbxassetid://483448923"
local ICON_MAP_URL = "https://raw.githubusercontent.com/TesterTD/BlatantExplorer/refs/heads/main/IconMap.png"
local ICON_MAP_ASSET = nil
local CODE_LINE_H = 17
local CODE_BUFFER = 15
local AUTO_UPDATE_PROPS = {
CFrame = true,
Position = true,
Orientation = true,
Rotation = true,
Velocity = true,
RotVelocity = true,
AssemblyLinearVelocity = true,
AssemblyAngularVelocity = true,
AssemblyCenterOfMass = true,
AssemblyMass = true,
}
local function initIconMapAsset()
if ICON_MAP_ASSET then
return ICON_MAP_ASSET
end
pcall(function()
if getcustomasset and writefile and isfile and makefolder and isfolder then
if not isfolder("BlatantExplorer") then
makefolder("BlatantExplorer")
end
local path = "BlatantExplorer/IconMap.png"
if not isfile(path) then
local req = (syn and syn.request) or (http and http.request) or request or http_request
if req then
local resp = req({ Url = ICON_MAP_URL, Method = "GET" })
if resp and resp.StatusCode and resp.StatusCode >= 200 and resp.StatusCode < 300 and resp.Body then
writefile(path, resp.Body)
end
else
local body = game:HttpGet(ICON_MAP_URL)
if body and #body > 0 then
writefile(path, body)
end
end
end
if isfile(path) then
local success, asset = pcall(getcustomasset, path)
if success and asset then
ICON_MAP_ASSET = asset
end
end
end
end)
return ICON_MAP_ASSET
end
local function getIconMapImage()
if ICON_MAP_ASSET then
return ICON_MAP_ASSET
end
local asset = initIconMapAsset()
if asset then
return asset
end
return ICON_MAP_ID
end
local function getFuncName(func)
local ok, result = pcall(function()
if debug.getinfo then
local info = debug.getinfo(func)
if info and info.name and info.name ~= "" then
return info.name
end
end
if debug.info then
local s, n, l = debug.info(func, "snl")
if n and n ~= "" then
return n
end
end
return nil
end)
if ok and result then
return result
end
return "Unknown Name"
end
local Theme = {
Bg = Color3.fromRGB(12, 14, 18),
Sf = Color3.fromRGB(15, 18, 22),
Top = Color3.fromRGB(18, 21, 25),
Inner = Color3.fromRGB(15, 18, 22),
Bd = Color3.fromRGB(35, 40, 45),
BdOuter = Color3.fromRGB(5, 8, 10),
Tx = Color3.fromRGB(210, 215, 220),
Sub = Color3.fromRGB(120, 130, 140),
Hi = Color3.fromRGB(0, 120, 170),
Hv = Color3.fromRGB(25, 28, 32),
CtxBg = Color3.fromRGB(18, 21, 25),
CtxHv = Color3.fromRGB(30, 35, 40),
CtxBd = Color3.fromRGB(35, 40, 45),
Err = Color3.fromRGB(220, 110, 110),
Acc = Color3.fromRGB(0, 180, 180),
AccAlt = Color3.fromRGB(0, 120, 200),
AccEnd = Color3.fromRGB(0, 255, 150),
Gutter = Color3.fromRGB(12, 14, 18),
GutterT = Color3.fromRGB(60, 65, 75),
CodeBg = Color3.fromRGB(10, 12, 16),
InputBg = Color3.fromRGB(25, 28, 32),
InputBd = Color3.fromRGB(5, 8, 10),
}
local ClassIcons = {
["Accessory"] = 32,
["Accoutrement"] = 32,
["Animation"] = 60,
["AnimationController"] = 60,
["Animator"] = 60,
["Atmosphere"] = 28,
["Attachment"] = 34,
["Backpack"] = 20,
["BallSocketConstraint"] = 34,
["Beam"] = 69,
["BillboardGui"] = 64,
["BindableEvent"] = 67,
["BindableFunction"] = 66,
["BlockMesh"] = 8,
["BloomEffect"] = 28,
["BlurEffect"] = 28,
["BodyAngularVelocity"] = 14,
["BodyForce"] = 14,
["BodyGyro"] = 14,
["BodyPosition"] = 14,
["BodyThrust"] = 14,
["BodyVelocity"] = 14,
["BoolValue"] = 4,
["Camera"] = 5,
["CFrameValue"] = 4,
["ClickDetector"] = 41,
["Clouds"] = 28,
["Color3Value"] = 4,
["ColorCorrectionEffect"] = 28,
["Configuration"] = 58,
["CoreGui"] = 46,
["CornerWedgePart"] = 1,
["CylinderMesh"] = 8,
["CylindricalConstraint"] = 34,
["Decal"] = 7,
["DepthOfFieldEffect"] = 28,
["Dialog"] = 62,
["DialogChoice"] = 62,
["Explosion"] = 36,
["FileMesh"] = 8,
["Fire"] = 61,
["Flag"] = 38,
["FlagStand"] = 39,
["Folder"] = 70,
["ForceField"] = 37,
["Frame"] = 48,
["Glue"] = 34,
["GuiButton"] = 52,
["GuiMain"] = 47,
["Handles"] = 53,
["Hat"] = 45,
["Highlight"] = 48,
["Hint"] = 33,
["HingeConstraint"] = 34,
["Humanoid"] = 9,
["HumanoidDescription"] = 9,
["ImageButton"] = 52,
["ImageLabel"] = 49,
["IntValue"] = 4,
["Keyframe"] = 60,
["KeyframeSequence"] = 60,
["Lighting"] = 13,
["LineForce"] = 14,
["LinearVelocity"] = 14,
["LocalScript"] = 18,
["ManualWeld"] = 34,
["MeshPart"] = 1,
["Message"] = 33,
["Model"] = 2,
["ModuleScript"] = 71,
["Motor"] = 34,
["Motor6D"] = 34,
["NegateOperation"] = 1,
["NetworkClient"] = 16,
["NumberValue"] = 4,
["ObjectValue"] = 4,
["Pants"] = 44,
["Part"] = 1,
["ParticleEmitter"] = 69,
["PartOperation"] = 1,
["Player"] = 12,
["PlayerGui"] = 46,
["Players"] = 21,
["PointLight"] = 13,
["Pose"] = 60,
["PrismaticConstraint"] = 34,
["ProximityPrompt"] = 41,
["RayValue"] = 4,
["RemoteEvent"] = 80,
["RemoteFunction"] = 79,
["ReplicatedFirst"] = 72,
["ReplicatedStorage"] = 72,
["RigidConstraint"] = 34,
["RodConstraint"] = 34,
["RopeConstraint"] = 34,
["ScreenGui"] = 47,
["Script"] = 6,
["ScrollingFrame"] = 48,
["Seat"] = 35,
["SelectionBox"] = 54,
["ServerScriptService"] = 0,
["ServerStorage"] = 74,
["Shirt"] = 43,
["Sky"] = 28,
["Smoke"] = 59,
["Sound"] = 11,
["SoundGroup"] = 11,
["SoundService"] = 31,
["SpawnLocation"] = 25,
["SpecialMesh"] = 8,
["SpotLight"] = 13,
["SpringConstraint"] = 34,
["StarterCharacterScripts"] = 82,
["StarterGui"] = 46,
["StarterPack"] = 20,
["StarterPlayer"] = 88,
["StarterPlayerScripts"] = 82,
["StringValue"] = 4,
["SunRaysEffect"] = 28,
["SurfaceAppearance"] = 10,
["SurfaceGui"] = 64,
["SurfaceLight"] = 13,
["Team"] = 24,
["Teams"] = 23,
["TeleportService"] = 81,
["Terrain"] = 65,
["TestService"] = 68,
["TextBox"] = 51,
["TextButton"] = 51,
["TextChatService"] = 15,
["TextLabel"] = 50,
["Texture"] = 10,
["Tool"] = 17,
["Torque"] = 14,
["TouchTransmitter"] = 37,
["Trail"] = 69,
["TrussPart"] = 1,
["UICorner"] = 48,
["UIGradient"] = 48,
["UIGridLayout"] = 48,
["UIListLayout"] = 48,
["UIPadding"] = 48,
["UIScale"] = 48,
["UIStroke"] = 48,
["UnionOperation"] = 1,
["Vector3Value"] = 4,
["VectorForce"] = 14,
["VehicleSeat"] = 35,
["VideoFrame"] = 49,
["ViewportFrame"] = 48,
["VoiceChatService"] = 31,
["WedgePart"] = 1,
["Weld"] = 34,
["WeldConstraint"] = 34,
["WorldModel"] = 2,
["Workspace"] = 19,
["WrapLayer"] = 10,
["WrapTarget"] = 10,
}
local ServiceOrder = {
["Workspace"] = 1,
["Players"] = 2,
["Lighting"] = 3,
["MaterialService"] = 4,
["NetworkClient"] = 5,
["ReplicatedFirst"] = 6,
["ReplicatedStorage"] = 7,
["ServerScriptService"] = 8,
["ServerStorage"] = 9,
["StarterGui"] = 10,
["StarterPack"] = 11,
["StarterPlayer"] = 12,
["Teams"] = 13,
["SoundService"] = 14,
["Chat"] = 15,
["TextChatService"] = 16,
["VoiceChatService"] = 17,
["LocalizationService"] = 18,
["TestService"] = 19,
}
local function new(class, props)
local inst = Instance.new(class)
if props then
for k, v in pairs(props) do
if k == "Parent" then
continue
end
inst[k] = v
end
if props.Parent then
inst.Parent = props.Parent
end
end
return inst
end
local function uid()
local rng = Random.new()
local chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
local out = ""
for _ = 1, 32 do
local r = rng:NextInteger(1, #chars)
out ..= chars:sub(r, r)
end
return out
end
local function splitLines(str)
local lines = {}
local pos = 1
while pos <= #str do
local nl = str:find("\n", pos, true)
if nl then
lines[#lines + 1] = str:sub(pos, nl - 1)
pos = nl + 1
else
lines[#lines + 1] = str:sub(pos)
break
end
end
if #lines == 0 then
lines[1] = ""
end
return lines
end
local function makeDraggable(bar, win)
local dragging, dragStart, startPos = false, nil, nil
bar.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
dragging = true
dragStart = input.Position
startPos = win.Position
local c
c = input.Changed:Connect(function()
if input.UserInputState == Enum.UserInputState.End then
dragging = false
if c then
c:Disconnect()
end
end
end)
end
end)
UserInputService.InputChanged:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseMovement and dragging then
local delta = input.Position - dragStart
win.Position = UDim2.new(
startPos.X.Scale, startPos.X.Offset + delta.X,
startPos.Y.Scale, startPos.Y.Offset + delta.Y
)
end
end)
end
local function ensureSaveFolder()
pcall(function()
if makefolder and isfolder then
if not isfolder("BlatantExplorer") then
makefolder("BlatantExplorer")
end
if not isfolder("BlatantExplorer/Saved") then
makefolder("BlatantExplorer/Saved")
end
end
end)
end
local Highlighter = {}
Highlighter.__index = Highlighter
function Highlighter.new()
return setmetatable({}, Highlighter)
end
function Highlighter:Tokenize(src)
local tokens = {}
local i = 1
local len = #src
while i <= len do
local c = src:byte(i)
if c == 45 and i < len and src:byte(i + 1) == 45 then
local rest = src:sub(i + 2, i + 3)
if rest == "[[" then
local closePos = src:find("%]%]", i + 4, false)
if closePos then
tokens[#tokens + 1] = { type = "comment", text = src:sub(i, closePos + 1) }
i = closePos + 2
else
tokens[#tokens + 1] = { type = "comment", text = src:sub(i) }
i = len + 1
end
elseif rest:sub(1, 1) == "[" then
local eqCount = 0
local j = i + 3
while j <= len and src:byte(j) == 61 do
eqCount += 1
j += 1
end
if j <= len and src:byte(j) == 91 then
local closePattern = "%]" .. ("="):rep(eqCount) .. "%]"
local closePos = src:find(closePattern, j + 1, false)
if closePos then
tokens[#tokens + 1] = { type = "comment", text = src:sub(i, closePos + eqCount + 1) }
i = closePos + eqCount + 2
else
tokens[#tokens + 1] = { type = "comment", text = src:sub(i) }
i = len + 1
end
else
local nl = src:find("\n", i, true)
if nl then
tokens[#tokens + 1] = { type = "comment", text = src:sub(i, nl - 1) }
i = nl
else
tokens[#tokens + 1] = { type = "comment", text = src:sub(i) }
i = len + 1
end
end
else
local nl = src:find("\n", i, true)
if nl then
tokens[#tokens + 1] = { type = "comment", text = src:sub(i, nl - 1) }
i = nl
else
tokens[#tokens + 1] = { type = "comment", text = src:sub(i) }
i = len + 1
end
end
elseif c == 91 then
local eqCount = 0
local j = i + 1
while j <= len and src:byte(j) == 61 do
eqCount += 1
j += 1
end
if j <= len and src:byte(j) == 91 then
local closePattern = "%]" .. ("="):rep(eqCount) .. "%]"
local closePos = src:find(closePattern, j + 1, false)
if closePos then
tokens[#tokens + 1] = { type = "string", text = src:sub(i, closePos + eqCount + 1) }
i = closePos + eqCount + 2
else
tokens[#tokens + 1] = { type = "string", text = src:sub(i) }
i = len + 1
end
else
tokens[#tokens + 1] = { type = "code", text = src:sub(i, i) }
i = i + 1
end
elseif c == 34 or c == 39 then
local quote = c
local j = i + 1
while j <= len do
local b = src:byte(j)
if b == 92 then
j = j + 2
elseif b == quote then
j = j + 1
break
elseif b == 10 then
break
else
j = j + 1
end
end
tokens[#tokens + 1] = { type = "string", text = src:sub(i, j - 1) }
i = j
elseif c == 10 then
tokens[#tokens + 1] = { type = "newline", text = "\n" }
i = i + 1
else
local j = i + 1
while j <= len do
local b = src:byte(j)
if b == 45 or b == 34 or b == 39 or b == 10 or b == 91 then
break
end
j = j + 1
end
tokens[#tokens + 1] = { type = "code", text = src:sub(i, j - 1) }
i = j
end
end
return tokens
end
function Highlighter:ColorCode(text)
local s = text
s = s:gsub("0x%x+", function(m)
return '<font color="#D19A66">' .. m .. "</font>"
end)
s = s:gsub("%f[%w_]%d+%.?%d*[eE]?[%+%-]?%d*%f[^%w_]", function(m)
return '<font color="#D19A66">' .. m .. "</font>"
end)
local kwSet = {
["and"] = true, ["break"] = true, ["do"] = true, ["else"] = true,
["elseif"] = true, ["end"] = true, ["for"] = true, ["function"] = true,
["if"] = true, ["in"] = true, ["local"] = true, ["not"] = true,
["or"] = true, ["repeat"] = true, ["return"] = true, ["then"] = true,
["until"] = true, ["while"] = true, ["continue"] = true,
}
local litSet = {
["true"] = true, ["false"] = true, ["nil"] = true, ["self"] = true,
}
local globSet = {
["game"] = true, ["workspace"] = true, ["script"] = true, ["math"] = true,
["string"] = true, ["table"] = true, ["task"] = true, ["wait"] = true,
["Enum"] = true, ["Instance"] = true, ["Color3"] = true, ["Vector3"] = true,
["Vector2"] = true, ["CFrame"] = true, ["UDim2"] = true, ["UDim"] = true,
["typeof"] = true, ["type"] = true, ["pcall"] = true, ["xpcall"] = true,
["coroutine"] = true, ["spawn"] = true, ["pairs"] = true, ["ipairs"] = true,
["next"] = true, ["tostring"] = true, ["tonumber"] = true, ["print"] = true,
["warn"] = true, ["error"] = true, ["require"] = true, ["rawget"] = true,
["rawset"] = true, ["rawequal"] = true, ["rawlen"] = true,
["setmetatable"] = true, ["getmetatable"] = true, ["select"] = true,
["unpack"] = true, ["tick"] = true, ["time"] = true, ["delay"] = true,
["assert"] = true, ["loadstring"] = true, ["newproxy"] = true,
}
s = s:gsub("%f[%w_][%a_][%w_]*%f[^%w_]", function(m)
if kwSet[m] then
return '<font color="#C678DD">' .. m .. "</font>"
end
if litSet[m] then
return '<font color="#D19A66">' .. m .. "</font>"
end
if globSet[m] then
return '<font color="#61AFEF">' .. m .. "</font>"
end
return m
end)
s = s:gsub(":[%a_][%w_]*", function(m)
return '<font color="#61AFEF">' .. m .. "</font>"
end)
return s
end
function Highlighter:Run(source)
local tokens = self:Tokenize(source)
local parts = {}
for _, tok in ipairs(tokens) do
local escaped = tok.text:gsub("&", "&"):gsub("<", "<"):gsub(">", ">")
if tok.type == "comment" then
parts[#parts + 1] = '<font color="#5C6370">' .. escaped .. "</font>"
elseif tok.type == "string" then
parts[#parts + 1] = '<font color="#98C379">' .. escaped .. "</font>"
elseif tok.type == "code" then
parts[#parts + 1] = self:ColorCode(escaped)
else
parts[#parts + 1] = escaped
end
end
return table.concat(parts)
end
function Highlighter:RunLines(source)
local tokens = self:Tokenize(source)
local lines = {}
local current = {}
local function flushLine()
lines[#lines + 1] = table.concat(current)
current = {}
end
for _, tok in ipairs(tokens) do
if tok.type == "newline" then
flushLine()
else
local escaped = tok.text:gsub("&", "&"):gsub("<", "<"):gsub(">", ">")
if escaped:find("\n", 1, true) then
local colorTag = ""
local closeTag = ""
if tok.type == "comment" then
colorTag = '<font color="#5C6370">'
closeTag = "</font>"
elseif tok.type == "string" then
colorTag = '<font color="#98C379">'
closeTag = "</font>"
end
local subLines = splitLines(escaped)
for si, sl in ipairs(subLines) do
if si > 1 then
flushLine()
end
if colorTag ~= "" then
current[#current + 1] = colorTag .. sl .. closeTag
elseif tok.type == "code" then
current[#current + 1] = self:ColorCode(sl)
else
current[#current + 1] = sl
end
end
else
if tok.type == "comment" then
current[#current + 1] = '<font color="#5C6370">' .. escaped .. "</font>"
elseif tok.type == "string" then
current[#current + 1] = '<font color="#98C379">' .. escaped .. "</font>"
elseif tok.type == "code" then
current[#current + 1] = self:ColorCode(escaped)
else
current[#current + 1] = escaped
end
end
end
end
flushLine()
return lines
end
local Explorer = {}
Explorer.__index = Explorer
function Explorer.new()
local self = setmetatable({}, Explorer)
self.Classes = {}
self.PropCache = {}
self.Nodes = {}
self.Flat = {}
self.Selected = {}
self._lastSelected = nil
self.Props = {}
self.PropConns = {}
self.TreeRows = {}
self.PropRows = {}
self.Clipboard = nil
self.RawSource = ""
self.HL = Highlighter.new()
self._visible = true
self._alive = true
self._nodeConns = {}
self._pendingUpdate = false
self._currentScriptInst = nil
self._viewMode = "decompile"
self._expandedNodes = {}
self._frameCount = 0
self._colorPickerPropIdx = nil
self._hlLines = {}
self._totalCodeLines = 0
self._codeLineH = CODE_LINE_H
self._codeLineHMeasured = false
self._lastRenderedFirst = -1
self._lastRenderedLast = -1
initIconMapAsset()
self:FetchAPI()
self:BuildUI()
self:BuildTree()
self:UpdateTree()
self._heartbeatConn = RunService.Heartbeat:Connect(function()
if not self._alive then
return
end
self._frameCount += 1
if self._frameCount % 6 ~= 0 then
return
end
if #self.Selected == 0 then
return
end
for _, row in ipairs(self.PropRows) do
if row.Frame.Visible and row.Idx >= 1 and row.Idx <= #self.Props then
local prop = self.Props[row.Idx]
if AUTO_UPDATE_PROPS[prop.Name] then
self:FmtProp(row)
end
end
end
end)
return self
end
function Explorer:GetPrimarySelected()
if self._lastSelected then
return self._lastSelected
end
if #self.Selected > 0 then
return self.Selected[#self.Selected]
end
return nil
end
function Explorer:IsSelected(inst)
for _, sel in ipairs(self.Selected) do
if sel == inst then
return true
end
end
return false
end
function Explorer:AddToSelection(inst)
if not self:IsSelected(inst) then
self.Selected[#self.Selected + 1] = inst
end
self._lastSelected = inst
end
function Explorer:RemoveFromSelection(inst)
for i, sel in ipairs(self.Selected) do
if sel == inst then
table.remove(self.Selected, i)
break
end
end
if self._lastSelected == inst then
self._lastSelected = if #self.Selected > 0 then self.Selected[#self.Selected] else nil
end
end
function Explorer:SetSingleSelection(inst)
self.Selected = { inst }
self._lastSelected = inst
end
function Explorer:ClearSelection()
self.Selected = {}
self._lastSelected = nil
end
function Explorer:Destroy()
self._alive = false
self:DisconnectAllNodes()
if self._heartbeatConn then
pcall(function()
self._heartbeatConn:Disconnect()
end)
end
if self.Gui then
pcall(function()
self.Gui:Destroy()
end)
end
end
function Explorer:ScheduleUpdate()
if self._pendingUpdate or not self._alive then
return
end
self._pendingUpdate = true
task.delay(0.3, function()
if not self._alive then
return
end
self._pendingUpdate = false
self:UpdateTree()
end)
end
function Explorer:ConnectNode(inst)
if self._nodeConns[inst] then
return
end
local conns = {}
local ok1, c1 = pcall(function()
return inst.ChildAdded:Connect(function()
if not self._alive then
return
end
for _, node in ipairs(self.Flat) do
if node.Instance == inst then
node.Children = nil
node.HasKids = nil
break
end
end
self:ScheduleUpdate()
end)
end)
if ok1 and c1 then
conns[#conns + 1] = c1
end
local ok2, c2 = pcall(function()
return inst.ChildRemoved:Connect(function(child)
if not self._alive then
return
end
if self:IsSelected(child) then
self:RemoveFromSelection(child)
if #self.Selected == 0 then
self:ClearProps()
else
self:LoadProperties(self:GetPrimarySelected())
end
end
for _, node in ipairs(self.Flat) do
if node.Instance == inst then
node.Children = nil
node.HasKids = nil
break
end
end
if self._nodeConns[child] then
for _, cn in ipairs(self._nodeConns[child]) do
pcall(function()
cn:Disconnect()
end)
end
self._nodeConns[child] = nil
end
self:ScheduleUpdate()
end)
end)
if ok2 and c2 then
conns[#conns + 1] = c2
end
if #conns > 0 then
self._nodeConns[inst] = conns
end
end
function Explorer:DisconnectAllNodes()
for _, conns in pairs(self._nodeConns) do
for _, conn in ipairs(conns) do
pcall(function()
conn:Disconnect()
end)
end
end
self._nodeConns = {}
end
function Explorer:FetchAPI()
local ok, data = pcall(function()
local ver = game:HttpGet("http://setup.roblox.com/versionQTStudio")
return HttpService:JSONDecode(
game:HttpGet("http://setup.roblox.com/" .. ver .. "-API-Dump.json")
)
end)
if not ok or not data then
return
end
for _, classData in ipairs(data.Classes) do
local props = {}
for _, member in ipairs(classData.Members) do
if member.MemberType ~= "Property" then
continue
end
local skip = false
if member.Tags then
for _, tag in ipairs(member.Tags) do
if tag == "Deprecated" or tag == "Hidden" or tag == "NotScriptable" then
skip = true
break
end
end
end
if not skip and member.Security then
local readSec = if type(member.Security) == "table"
then member.Security.Read
else member.Security
if readSec and readSec ~= "None" and readSec ~= "PluginSecurity" then
skip = true
end
end
if not skip then
props[#props + 1] = {
Name = member.Name,
ValueType = if member.ValueType then member.ValueType.Name else "string",
Category = member.Category or "Data",
}
end
end
if classData.ExplorerImageIndex and not ClassIcons[classData.Name] then
ClassIcons[classData.Name] = classData.ExplorerImageIndex
end
self.Classes[classData.Name] = {
Name = classData.Name,
Superclass = classData.Superclass,
Properties = props,
}
end
end
function Explorer:ApplyIcon(iconFrame, className)
local idx = ClassIcons[className] or 0
local col = math.floor(idx % ICON_COLS)
local row = math.floor(idx / ICON_COLS % ICON_COLS)
iconFrame.ClipsDescendants = true
local img = iconFrame:FindFirstChild("IconMap")
if not img then
img = new("ImageLabel", {
Name = "IconMap",
BackgroundTransparency = 1,
Image = getIconMapImage(),
ScaleType = Enum.ScaleType.Stretch,
Parent = iconFrame,
})
else
local currentImage = getIconMapImage()
if img.Image ~= currentImage then
img.Image = currentImage
end
end
local scale = ICON_MAP_SIZE / ICON_SZ
img.Size = UDim2.new(scale, 0, scale, 0)
img.Position = UDim2.new(
-col - (ICON_PAD * (col + 1) + ICON_BORDER) / ICON_SZ, 0,
-row - (ICON_PAD * (row + 1) + ICON_BORDER) / ICON_SZ, 0
)
end
function Explorer:GetProps(className)
if self.PropCache[className] then
return self.PropCache[className]
end
local props, seen, current = {}, {}, className
while current do
local cls = self.Classes[current]
if not cls then
break
end
for _, prop in ipairs(cls.Properties) do
if not seen[prop.Name] then
seen[prop.Name] = true
props[#props + 1] = prop
end
end
current = cls.Superclass
end
table.sort(props, function(a, b)
return a.Name < b.Name
end)
self.PropCache[className] = props
return props
end
function Explorer:FullPath(inst)
local parts, current = {}, inst
while current and current ~= game do
local name = current.Name
if name:match("^[%a_][%w_]*$") then
table.insert(parts, 1, "." .. name)
else
table.insert(parts, 1, '["' .. name .. '"]')
end
current = current.Parent
end
if #parts == 0 then
return "game"
end
return "game" .. table.concat(parts)
end
function Explorer:HasChildren(node)
if node.HasKids ~= nil then
return node.HasKids
end
if node.Instance.Name == "Nil Instances" and node.Depth == 0 then
node.HasKids = #getnil() > 0
return node.HasKids
end
local ok, children = pcall(function()
return node.Instance:GetChildren()
end)
node.HasKids = ok and children and #children > 0
return node.HasKids
end
function Explorer:HideCtx()
if self.CtxWrap then
self.CtxWrap.Visible = false
end
end
function Explorer:CtxVisible()
return self.CtxWrap ~= nil and self.CtxWrap.Visible
end
function Explorer:HideColorPicker()
if self.ColorPickerWrap then
self.ColorPickerWrap.Visible = false
end
self._colorPickerPropIdx = nil
end
function Explorer:ShowColorPicker(propIdx, btn)
self._colorPickerPropIdx = propIdx
local absPos = btn.AbsolutePosition
local absSize = btn.AbsoluteSize
local screenX = absPos.X + absSize.X + 4
local screenY = absPos.Y
pcall(function()
local vpSize = workspace.CurrentCamera.ViewportSize
if screenX + 262 > vpSize.X then
screenX = absPos.X - 262
end
if screenY + 282 > vpSize.Y then
screenY = vpSize.Y - 282
end
end)
self.ColorPickerWrap.Position = UDim2.new(0, screenX, 0, screenY)
self.ColorPickerWrap.Visible = true
end
function Explorer:OnTreeRMB(row)
if row.Idx < 1 or row.Idx > #self.Flat then
return
end
local node = self.Flat[row.Idx]
if not self:IsSelected(node.Instance) then
self:SetSingleSelection(node.Instance)
end
self:RenderTree()
self:LoadProperties(self:GetPrimarySelected())
self:ShowCtx(node.Instance)
end
function Explorer:BuildUI()
self.Gui = new("ScreenGui", {
Name = uid(),
ResetOnSpawn = false,
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
Parent = gethui_func(),
})
self.Window = new("Frame", {
Size = UDim2.new(0, 820, 0, 520),
Position = UDim2.new(0.5, -410, 0.5, -260),
BackgroundColor3 = Theme.BdOuter,
BorderSizePixel = 0,
Active = true,
Parent = self.Gui,
})
self.InnerBorder = new("Frame", {
Size = UDim2.new(1, -2, 1, -2),
Position = UDim2.new(0, 1, 0, 1),
BackgroundColor3 = Theme.Inner,
BorderColor3 = Theme.Bd,
BorderSizePixel = 1,
ClipsDescendants = true,
Parent = self.Window,
})
local topLine = new("Frame", {
Size = UDim2.new(1, 0, 0, 2),
BackgroundColor3 = Color3.new(1, 1, 1),
BorderSizePixel = 0,
ZIndex = 5,
Parent = self.InnerBorder,
})
new("UIGradient", {
Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Theme.AccAlt),
ColorSequenceKeypoint.new(0.5, Theme.Acc),
ColorSequenceKeypoint.new(1, Theme.AccEnd),
}),
Parent = topLine,
})
new("TextLabel", {
Size = UDim2.new(1, -16, 0, 22),
Position = UDim2.new(0, 8, 0, 2),
BackgroundTransparency = 1,
Text = "BlatantExplorer",
TextColor3 = Theme.Tx,
Font = Enum.Font.GothamBold,
TextSize = 13,
TextXAlignment = Enum.TextXAlignment.Left,
ZIndex = 5,
Parent = self.InnerBorder,
})
makeDraggable(self.InnerBorder, self.Window)
new("Frame", {
Size = UDim2.new(1, 0, 0, 1),
Position = UDim2.new(0, 0, 0, 24),
BackgroundColor3 = Theme.Bd,
BorderSizePixel = 0,
ZIndex = 5,
Parent = self.InnerBorder,
})
local leftPanel = new("Frame", {
Size = UDim2.new(0, 310, 1, -25),
Position = UDim2.new(0, 0, 0, 25),
BackgroundColor3 = Theme.Bg,
BorderColor3 = Theme.Bd,
BorderSizePixel = 1,
ClipsDescendants = true,
Parent = self.InnerBorder,
})
self.TreeScroll = new("ScrollingFrame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
ScrollBarThickness = 3,
ScrollBarImageColor3 = Theme.Acc,
ScrollBarImageTransparency = 0.4,
CanvasSize = UDim2.new(0, 0, 0, 0),
BorderSizePixel = 0,
Parent = leftPanel,
})
new("Frame", {
Size = UDim2.new(0, 1, 1, -25),
Position = UDim2.new(0, 310, 0, 25),
BackgroundColor3 = Theme.Bd,
BorderSizePixel = 0,
ZIndex = 5,
Parent = self.InnerBorder,
})
local rightPanel = new("Frame", {
Size = UDim2.new(1, -311, 1, -25),
Position = UDim2.new(0, 311, 0, 25),
BackgroundColor3 = Theme.Sf,
BorderSizePixel = 0,
ClipsDescendants = true,
Parent = self.InnerBorder,
})
self.PropScroll = new("ScrollingFrame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
ScrollBarThickness = 3,
ScrollBarImageColor3 = Theme.Acc,
ScrollBarImageTransparency = 0.4,
CanvasSize = UDim2.new(0, 0, 0, 0),
BorderSizePixel = 0,
Parent = rightPanel,
})
self:BuildScriptViewer()
self:BuildContextMenu()
self:BuildTreeRows()
self:BuildPropRows()
self:BuildColorPicker()
self.TreeScroll:GetPropertyChangedSignal("CanvasPosition"):Connect(function()
self:RenderTree()
end)
self.PropScroll:GetPropertyChangedSignal("CanvasPosition"):Connect(function()
self:RenderProps()
end)
UserInputService.InputBegan:Connect(function(input, gpe)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if self:CtxVisible() then
local mousePos = UserInputService:GetMouseLocation()
local inset = GuiService:GetGuiInset()
local mx, my = mousePos.X, mousePos.Y - inset.Y
local pos = self.CtxFrame.AbsolutePosition
local sz = self.CtxFrame.AbsoluteSize
if mx < pos.X or mx > pos.X + sz.X or my < pos.Y or my > pos.Y + sz.Y then
self:HideCtx()
end
end
if self.ColorPickerWrap and self.ColorPickerWrap.Visible then
local mousePos = UserInputService:GetMouseLocation()
local inset = GuiService:GetGuiInset()
local mx, my = mousePos.X, mousePos.Y - inset.Y
local pos = self.ColorPickerWrap.AbsolutePosition
local sz = self.ColorPickerWrap.AbsoluteSize
if mx < pos.X or mx > pos.X + sz.X or my < pos.Y or my > pos.Y + sz.Y then
self:HideColorPicker()
end
end
end
if not gpe and input.KeyCode == Enum.KeyCode.F3 then
self._visible = not self._visible
self.Gui.Enabled = self._visible
if self.ScriptWin then
self.ScriptWin.Visible = false
end
self:HideColorPicker()
end
end)
end
function Explorer:_makeViewerBtn(parent, text, posX, zIdx)
local btn = new("TextButton", {
Size = UDim2.new(0, 60, 0, 18),
Position = UDim2.new(1, posX, 0, 4),
BackgroundColor3 = Theme.InputBg,
BorderColor3 = Theme.InputBd,
BorderSizePixel = 1,
Text = text,
TextColor3 = Theme.Sub,
Font = Enum.Font.GothamMedium,
TextSize = 11,
ZIndex = zIdx,
AutoButtonColor = false,
Parent = parent,
})
btn.MouseEnter:Connect(function()
btn.BackgroundColor3 = Theme.CtxHv
btn.TextColor3 = Theme.Tx
end)
btn.MouseLeave:Connect(function()
btn.BackgroundColor3 = Theme.InputBg
btn.TextColor3 = Theme.Sub
end)
return btn
end
function Explorer:BuildScriptViewer()
self.ScriptWin = new("Frame", {
Size = UDim2.new(0, 740, 0, 500),
Position = UDim2.new(0.5, -370, 0.5, -250),
BackgroundColor3 = Theme.BdOuter,
BorderSizePixel = 0,
Active = true,
Visible = false,
ZIndex = 10,
Parent = self.Gui,
})
local scriptInner = new("Frame", {
Size = UDim2.new(1, -2, 1, -2),
Position = UDim2.new(0, 1, 0, 1),
BackgroundColor3 = Theme.Inner,
BorderColor3 = Theme.Bd,
BorderSizePixel = 1,
ClipsDescendants = true,
ZIndex = 10,
Parent = self.ScriptWin,
})
local sTopLine = new("Frame", {
Size = UDim2.new(1, 0, 0, 2),
BackgroundColor3 = Color3.new(1, 1, 1),
BorderSizePixel = 0,
ZIndex = 11,
Parent = scriptInner,
})
new("UIGradient", {
Color = ColorSequence.new({
ColorSequenceKeypoint.new(0, Color3.fromRGB(0, 200, 100)),
ColorSequenceKeypoint.new(0.5, Theme.Acc),
ColorSequenceKeypoint.new(1, Theme.AccAlt),
}),
Parent = sTopLine,
})
self.ScriptTitle = new("TextLabel", {
Size = UDim2.new(1, -300, 0, 22),
Position = UDim2.new(0, 8, 0, 2),
BackgroundTransparency = 1,
Text = "Script Viewer",
TextColor3 = Theme.Tx,
TextXAlignment = Enum.TextXAlignment.Left,
Font = Enum.Font.GothamBold,
TextSize = 12,
ZIndex = 11,
Parent = scriptInner,
})
local saveBtn = self:_makeViewerBtn(scriptInner, "Save", -298, 12)
local saveBytecodeBtn = self:_makeViewerBtn(scriptInner, "Bytecode", -232, 12)
self.DumpBtn = self:_makeViewerBtn(scriptInner, "Dump", -166, 12)
local copyBtn = self:_makeViewerBtn(scriptInner, "Copy", -100, 12)
saveBtn.MouseButton1Click:Connect(function()
if not self._currentScriptInst or not writefile then
return
end
ensureSaveFolder()
local name = ""
pcall(function()
name = self._currentScriptInst.Name
end)
local safeName = name:gsub("[^%w_%-]", "_")
if safeName == "" then
safeName = "script"
end
local src = self.RawSource
if #src == 0 then
local ok2, dec = pcall(decompile_func, self._currentScriptInst)
if ok2 and type(dec) == "string" then
src = dec
end
end
if #src > 0 then
local ok3 = pcall(function()
writefile("BlatantExplorer/Saved/" .. safeName .. ".lua", src)
end)
if ok3 then
saveBtn.Text = "Saved!"
saveBtn.TextColor3 = Theme.Acc
task.delay(1.5, function()
saveBtn.Text = "Save"
saveBtn.TextColor3 = Theme.Sub
end)
end
end
end)
saveBytecodeBtn.MouseButton1Click:Connect(function()
if not self._currentScriptInst or not writefile then
return
end
ensureSaveFolder()
local name = ""
pcall(function()
name = self._currentScriptInst.Name
end)
local safeName = name:gsub("[^%w_%-]", "_")
if safeName == "" then
safeName = "script"
end
local ok, bytecode = pcall(getscriptbytecode_func, self._currentScriptInst)
if ok and bytecode and #bytecode > 0 then
local ok2 = pcall(function()
writefile("BlatantExplorer/Saved/" .. safeName .. ".bytecode", bytecode)
end)
if ok2 then
saveBytecodeBtn.Text = "Saved!"
saveBytecodeBtn.TextColor3 = Theme.Acc
task.delay(1.5, function()
saveBytecodeBtn.Text = "Bytecode"
saveBytecodeBtn.TextColor3 = Theme.Sub
end)
else
saveBytecodeBtn.Text = "Error"
saveBytecodeBtn.TextColor3 = Theme.Err
task.delay(1.5, function()
saveBytecodeBtn.Text = "Bytecode"
saveBytecodeBtn.TextColor3 = Theme.Sub
end)
end
else
saveBytecodeBtn.Text = "N/A"
saveBytecodeBtn.TextColor3 = Theme.Err
task.delay(1.5, function()
saveBytecodeBtn.Text = "Bytecode"
saveBytecodeBtn.TextColor3 = Theme.Sub
end)
end
end)
self.DumpBtn.MouseButton1Click:Connect(function()
if not self._currentScriptInst then
return
end
if self._viewMode == "decompile" then
self._viewMode = "dump"
self.DumpBtn.Text = "Decompile"
self:DumpScript(self._currentScriptInst)
else
self._viewMode = "decompile"
self.DumpBtn.Text = "Dump"
self:OpenScript(self._currentScriptInst)
end
end)
copyBtn.MouseButton1Click:Connect(function()
local clipboardFn = setclipboard or toclipboard or set_clipboard or (Clipboard and Clipboard.set)
if clipboardFn and #self.RawSource > 0 then
clipboardFn(self.RawSource)
copyBtn.Text = "Done"
copyBtn.TextColor3 = Theme.Acc
task.delay(1.5, function()
copyBtn.Text = "Copy"
copyBtn.TextColor3 = Theme.Sub
end)
end
end)
local closeBtn = new("TextButton", {
Size = UDim2.new(0, 32, 0, 22),
Position = UDim2.new(1, -32, 0, 2),
BackgroundTransparency = 1,
Text = "x",
TextColor3 = Theme.Sub,
Font = Enum.Font.GothamBold,
TextSize = 14,
ZIndex = 12,
Parent = scriptInner,
})
closeBtn.MouseButton1Click:Connect(function()
self.ScriptWin.Visible = false
end)
closeBtn.MouseEnter:Connect(function()
closeBtn.TextColor3 = Theme.Err
end)
closeBtn.MouseLeave:Connect(function()
closeBtn.TextColor3 = Theme.Sub
end)
makeDraggable(scriptInner, self.ScriptWin)
new("Frame", {
Size = UDim2.new(1, 0, 0, 1),
Position = UDim2.new(0, 0, 0, 24),
BackgroundColor3 = Theme.Bd,
BorderSizePixel = 0,
ZIndex = 11,
Parent = scriptInner,
})
local body = new("Frame", {
Size = UDim2.new(1, 0, 1, -25),
Position = UDim2.new(0, 0, 0, 25),
BackgroundColor3 = Theme.CodeBg,
BorderSizePixel = 0,
ZIndex = 10,
ClipsDescendants = true,
Parent = scriptInner,
})
local gutterBg = new("Frame", {
Size = UDim2.new(0, GUTTER_W, 1, 0),
BackgroundColor3 = Theme.Gutter,
BorderSizePixel = 0,
ZIndex = 10,
ClipsDescendants = true,
Parent = body,
})
self.GutterScroll = new("ScrollingFrame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
ScrollBarThickness = 0,
CanvasSize = UDim2.new(0, 0, 0, 0),
ScrollingEnabled = false,
BorderSizePixel = 0,
ZIndex = 10,
Parent = gutterBg,
})
self.GutterLabel = new("TextLabel", {
Size = UDim2.new(1, -10, 1, 0),
Position = UDim2.new(0, 0, 0, 0),
BackgroundTransparency = 1,
TextXAlignment = Enum.TextXAlignment.Right,
TextYAlignment = Enum.TextYAlignment.Top,
TextColor3 = Theme.GutterT,
Font = Enum.Font.Code,
TextSize = 14,
TextWrapped = false,
Text = "",
ZIndex = 10,
Parent = self.GutterScroll,
})
new("Frame", {
Size = UDim2.new(0, 1, 1, 0),
Position = UDim2.new(0, GUTTER_W, 0, 0),
BackgroundColor3 = Theme.Bd,
BackgroundTransparency = 0.5,
BorderSizePixel = 0,
ZIndex = 10,
Parent = body,
})
self.CodeScroll = new("ScrollingFrame", {
Size = UDim2.new(1, -(GUTTER_W + 1), 1, 0),
Position = UDim2.new(0, GUTTER_W + 1, 0, 0),
BackgroundTransparency = 1,
ScrollBarThickness = 4,
ScrollBarImageColor3 = Theme.Acc,
ScrollBarImageTransparency = 0.5,
CanvasSize = UDim2.new(0, 0, 0, 0),
BorderSizePixel = 0,
ZIndex = 10,
Parent = body,
})
self.CodeLabel = new("TextLabel", {
Size = UDim2.new(0, 6000, 0, 100),
Position = UDim2.new(0, 12, 0, 0),
BackgroundTransparency = 1,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Top,
RichText = true,
TextColor3 = Theme.Tx,
Font = Enum.Font.Code,
TextSize = 14,
TextWrapped = false,
Text = "",
ZIndex = 10,
Parent = self.CodeScroll,
})
self.CodeScroll:GetPropertyChangedSignal("CanvasPosition"):Connect(function()
self.GutterScroll.CanvasPosition = Vector2.new(0, self.CodeScroll.CanvasPosition.Y)
self:RenderCodeView()
end)
end
function Explorer:SetViewerContent(hlLines)
self._hlLines = hlLines
self._totalCodeLines = #hlLines
self._lastRenderedFirst = -1
self._lastRenderedLast = -1
self._codeLineHMeasured = false
local totalH = self._totalCodeLines * self._codeLineH + 24
self.CodeScroll.CanvasSize = UDim2.newAdvertisements
Comments
0Did it work for you? Sign in to share your experience.
No comments yet
Tried it? Let others know if it works.