Sapphinxscriptt

Untitled

Apr 19th, 2024
25
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 76.39 KB | None | 0 0
  1. -- shuts down the previous instance of SimpleSpy
  2. if _G.SimpleSpyExecuted and type(_G.SimpleSpyShutdown) == "function" then
  3. _G.SimpleSpyShutdown()
  4. end
  5.  
  6. local Players = game:GetService("Players")
  7. local CoreGui = game:GetService("CoreGui")
  8. local Highlight = loadstring(game:HttpGet("https://github.com/exxtremestuffs/SimpleSpySource/raw/master/highlight.lua"))()
  9.  
  10. ---- GENERATED (kinda sorta mostly) BY GUI to LUA ----
  11.  
  12. -- Instances:
  13.  
  14. local SimpleSpy2 = Instance.new("ScreenGui")
  15. local Background = Instance.new("Frame")
  16. local LeftPanel = Instance.new("Frame")
  17. local LogList = Instance.new("ScrollingFrame")
  18. local UIListLayout = Instance.new("UIListLayout")
  19. local RemoteTemplate = Instance.new("Frame")
  20. local ColorBar = Instance.new("Frame")
  21. local Text = Instance.new("TextLabel")
  22. local Button = Instance.new("TextButton")
  23. local RightPanel = Instance.new("Frame")
  24. local CodeBox = Instance.new("Frame")
  25. local ScrollingFrame = Instance.new("ScrollingFrame")
  26. local UIGridLayout = Instance.new("UIGridLayout")
  27. local FunctionTemplate = Instance.new("Frame")
  28. local ColorBar_2 = Instance.new("Frame")
  29. local Text_2 = Instance.new("TextLabel")
  30. local Button_2 = Instance.new("TextButton")
  31. local TopBar = Instance.new("Frame")
  32. local Simple = Instance.new("TextButton")
  33. local CloseButton = Instance.new("TextButton")
  34. local ImageLabel = Instance.new("ImageLabel")
  35. local MaximizeButton = Instance.new("TextButton")
  36. local ImageLabel_2 = Instance.new("ImageLabel")
  37. local MinimizeButton = Instance.new("TextButton")
  38. local ImageLabel_3 = Instance.new("ImageLabel")
  39. local ToolTip = Instance.new("Frame")
  40. local TextLabel = Instance.new("TextLabel")
  41.  
  42. --Properties:
  43.  
  44. SimpleSpy2.Name = "SimpleSpy2"
  45. SimpleSpy2.ResetOnSpawn = false
  46.  
  47. Background.Name = "Background"
  48. Background.Parent = SimpleSpy2
  49. Background.BackgroundColor3 = Color3.new(1, 1, 1)
  50. Background.BackgroundTransparency = 1
  51. Background.Position = UDim2.new(0, 500, 0, 200)
  52. Background.Size = UDim2.new(0, 450, 0, 268)
  53.  
  54. LeftPanel.Name = "LeftPanel"
  55. LeftPanel.Parent = Background
  56. LeftPanel.BackgroundColor3 = Color3.new(0.207843, 0.203922, 0.215686)
  57. LeftPanel.BorderSizePixel = 0
  58. LeftPanel.Position = UDim2.new(0, 0, 0, 19)
  59. LeftPanel.Size = UDim2.new(0, 131, 0, 249)
  60.  
  61. LogList.Name = "LogList"
  62. LogList.Parent = LeftPanel
  63. LogList.Active = true
  64. LogList.BackgroundColor3 = Color3.new(1, 1, 1)
  65. LogList.BackgroundTransparency = 1
  66. LogList.BorderSizePixel = 0
  67. LogList.Position = UDim2.new(0, 0, 0, 9)
  68. LogList.Size = UDim2.new(0, 131, 0, 232)
  69. LogList.CanvasSize = UDim2.new(0, 0, 0, 0)
  70. LogList.ScrollBarThickness = 4
  71.  
  72. UIListLayout.Parent = LogList
  73. UIListLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
  74. UIListLayout.SortOrder = Enum.SortOrder.LayoutOrder
  75.  
  76. RemoteTemplate.Name = "RemoteTemplate"
  77. RemoteTemplate.Parent = LogList
  78. RemoteTemplate.BackgroundColor3 = Color3.new(1, 1, 1)
  79. RemoteTemplate.BackgroundTransparency = 1
  80. RemoteTemplate.Size = UDim2.new(0, 117, 0, 27)
  81.  
  82. ColorBar.Name = "ColorBar"
  83. ColorBar.Parent = RemoteTemplate
  84. ColorBar.BackgroundColor3 = Color3.new(1, 0.94902, 0)
  85. ColorBar.BorderSizePixel = 0
  86. ColorBar.Position = UDim2.new(0, 0, 0, 1)
  87. ColorBar.Size = UDim2.new(0, 7, 0, 18)
  88. ColorBar.ZIndex = 2
  89.  
  90. Text.Name = "Text"
  91. Text.Parent = RemoteTemplate
  92. Text.BackgroundColor3 = Color3.new(1, 1, 1)
  93. Text.BackgroundTransparency = 1
  94. Text.Position = UDim2.new(0, 12, 0, 1)
  95. Text.Size = UDim2.new(0, 105, 0, 18)
  96. Text.ZIndex = 2
  97. Text.Font = Enum.Font.SourceSans
  98. Text.Text = "TEXT"
  99. Text.TextColor3 = Color3.new(1, 1, 1)
  100. Text.TextSize = 14
  101. Text.TextXAlignment = Enum.TextXAlignment.Left
  102.  
  103. Button.Name = "Button"
  104. Button.Parent = RemoteTemplate
  105. Button.BackgroundColor3 = Color3.new(0, 0, 0)
  106. Button.BackgroundTransparency = 0.75
  107. Button.BorderColor3 = Color3.new(1, 1, 1)
  108. Button.Position = UDim2.new(0, 0, 0, 1)
  109. Button.Size = UDim2.new(0, 117, 0, 18)
  110. Button.AutoButtonColor = false
  111. Button.Font = Enum.Font.SourceSans
  112. Button.Text = ""
  113. Button.TextColor3 = Color3.new(0, 0, 0)
  114. Button.TextSize = 14
  115.  
  116. RightPanel.Name = "RightPanel"
  117. RightPanel.Parent = Background
  118. RightPanel.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  119. RightPanel.BorderSizePixel = 0
  120. RightPanel.Position = UDim2.new(0, 131, 0, 19)
  121. RightPanel.Size = UDim2.new(0, 319, 0, 249)
  122.  
  123. CodeBox.Name = "CodeBox"
  124. CodeBox.Parent = RightPanel
  125. CodeBox.BackgroundColor3 = Color3.new(0.0823529, 0.0745098, 0.0784314)
  126. CodeBox.BorderSizePixel = 0
  127. CodeBox.Size = UDim2.new(0, 319, 0, 119)
  128.  
  129. ScrollingFrame.Parent = RightPanel
  130. ScrollingFrame.Active = true
  131. ScrollingFrame.BackgroundColor3 = Color3.new(1, 1, 1)
  132. ScrollingFrame.BackgroundTransparency = 1
  133. ScrollingFrame.Position = UDim2.new(0, 0, 0.5, 0)
  134. ScrollingFrame.Size = UDim2.new(1, 0, 0.5, -9)
  135. ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
  136. ScrollingFrame.ScrollBarThickness = 4
  137.  
  138. UIGridLayout.Parent = ScrollingFrame
  139. UIGridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
  140. UIGridLayout.SortOrder = Enum.SortOrder.LayoutOrder
  141. UIGridLayout.CellPadding = UDim2.new(0, 0, 0, 0)
  142. UIGridLayout.CellSize = UDim2.new(0, 94, 0, 27)
  143.  
  144. FunctionTemplate.Name = "FunctionTemplate"
  145. FunctionTemplate.Parent = ScrollingFrame
  146. FunctionTemplate.BackgroundColor3 = Color3.new(1, 1, 1)
  147. FunctionTemplate.BackgroundTransparency = 1
  148. FunctionTemplate.Size = UDim2.new(0, 117, 0, 23)
  149.  
  150. ColorBar_2.Name = "ColorBar"
  151. ColorBar_2.Parent = FunctionTemplate
  152. ColorBar_2.BackgroundColor3 = Color3.new(1, 1, 1)
  153. ColorBar_2.BorderSizePixel = 0
  154. ColorBar_2.Position = UDim2.new(0, 7, 0, 10)
  155. ColorBar_2.Size = UDim2.new(0, 7, 0, 18)
  156. ColorBar_2.ZIndex = 3
  157.  
  158. Text_2.Name = "Text"
  159. Text_2.Parent = FunctionTemplate
  160. Text_2.BackgroundColor3 = Color3.new(1, 1, 1)
  161. Text_2.BackgroundTransparency = 1
  162. Text_2.Position = UDim2.new(0, 19, 0, 10)
  163. Text_2.Size = UDim2.new(0, 69, 0, 18)
  164. Text_2.ZIndex = 2
  165. Text_2.Font = Enum.Font.SourceSans
  166. Text_2.Text = "TEXT"
  167. Text_2.TextColor3 = Color3.new(1, 1, 1)
  168. Text_2.TextSize = 14
  169. Text_2.TextStrokeColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  170. Text_2.TextXAlignment = Enum.TextXAlignment.Left
  171.  
  172. Button_2.Name = "Button"
  173. Button_2.Parent = FunctionTemplate
  174. Button_2.BackgroundColor3 = Color3.new(0, 0, 0)
  175. Button_2.BackgroundTransparency = 0.69999998807907
  176. Button_2.BorderColor3 = Color3.new(1, 1, 1)
  177. Button_2.Position = UDim2.new(0, 7, 0, 10)
  178. Button_2.Size = UDim2.new(0, 80, 0, 18)
  179. Button_2.AutoButtonColor = false
  180. Button_2.Font = Enum.Font.SourceSans
  181. Button_2.Text = ""
  182. Button_2.TextColor3 = Color3.new(0, 0, 0)
  183. Button_2.TextSize = 14
  184.  
  185. TopBar.Name = "TopBar"
  186. TopBar.Parent = Background
  187. TopBar.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  188. TopBar.BorderSizePixel = 0
  189. TopBar.Size = UDim2.new(0, 450, 0, 19)
  190.  
  191. Simple.Name = "Simple"
  192. Simple.Parent = TopBar
  193. Simple.BackgroundColor3 = Color3.new(1, 1, 1)
  194. Simple.AutoButtonColor = false
  195. Simple.BackgroundTransparency = 1
  196. Simple.Position = UDim2.new(0, 5, 0, 0)
  197. Simple.Size = UDim2.new(0, 57, 0, 18)
  198. Simple.Font = Enum.Font.SourceSansBold
  199. Simple.Text = "SimpleSpy"
  200. Simple.TextColor3 = Color3.new(1, 1, 1)
  201. Simple.TextSize = 14
  202. Simple.TextXAlignment = Enum.TextXAlignment.Left
  203.  
  204. CloseButton.Name = "CloseButton"
  205. CloseButton.Parent = TopBar
  206. CloseButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  207. CloseButton.BorderSizePixel = 0
  208. CloseButton.Position = UDim2.new(1, -19, 0, 0)
  209. CloseButton.Size = UDim2.new(0, 19, 0, 19)
  210. CloseButton.Font = Enum.Font.SourceSans
  211. CloseButton.Text = ""
  212. CloseButton.TextColor3 = Color3.new(0, 0, 0)
  213. CloseButton.TextSize = 14
  214.  
  215. ImageLabel.Parent = CloseButton
  216. ImageLabel.BackgroundColor3 = Color3.new(1, 1, 1)
  217. ImageLabel.BackgroundTransparency = 1
  218. ImageLabel.Position = UDim2.new(0, 5, 0, 5)
  219. ImageLabel.Size = UDim2.new(0, 9, 0, 9)
  220. ImageLabel.Image = "http://www.roblox.com/asset/?id=5597086202"
  221.  
  222. MaximizeButton.Name = "MaximizeButton"
  223. MaximizeButton.Parent = TopBar
  224. MaximizeButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  225. MaximizeButton.BorderSizePixel = 0
  226. MaximizeButton.Position = UDim2.new(1, -38, 0, 0)
  227. MaximizeButton.Size = UDim2.new(0, 19, 0, 19)
  228. MaximizeButton.Font = Enum.Font.SourceSans
  229. MaximizeButton.Text = ""
  230. MaximizeButton.TextColor3 = Color3.new(0, 0, 0)
  231. MaximizeButton.TextSize = 14
  232.  
  233. ImageLabel_2.Parent = MaximizeButton
  234. ImageLabel_2.BackgroundColor3 = Color3.new(1, 1, 1)
  235. ImageLabel_2.BackgroundTransparency = 1
  236. ImageLabel_2.Position = UDim2.new(0, 5, 0, 5)
  237. ImageLabel_2.Size = UDim2.new(0, 9, 0, 9)
  238. ImageLabel_2.Image = "http://www.roblox.com/asset/?id=5597108117"
  239.  
  240. MinimizeButton.Name = "MinimizeButton"
  241. MinimizeButton.Parent = TopBar
  242. MinimizeButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  243. MinimizeButton.BorderSizePixel = 0
  244. MinimizeButton.Position = UDim2.new(1, -57, 0, 0)
  245. MinimizeButton.Size = UDim2.new(0, 19, 0, 19)
  246. MinimizeButton.Font = Enum.Font.SourceSans
  247. MinimizeButton.Text = ""
  248. MinimizeButton.TextColor3 = Color3.new(0, 0, 0)
  249. MinimizeButton.TextSize = 14
  250.  
  251. ImageLabel_3.Parent = MinimizeButton
  252. ImageLabel_3.BackgroundColor3 = Color3.new(1, 1, 1)
  253. ImageLabel_3.BackgroundTransparency = 1
  254. ImageLabel_3.Position = UDim2.new(0, 5, 0, 5)
  255. ImageLabel_3.Size = UDim2.new(0, 9, 0, 9)
  256. ImageLabel_3.Image = "http://www.roblox.com/asset/?id=5597105827"
  257.  
  258. ToolTip.Name = "ToolTip"
  259. ToolTip.Parent = SimpleSpy2
  260. ToolTip.BackgroundColor3 = Color3.fromRGB(26, 26, 26)
  261. ToolTip.BackgroundTransparency = 0.1
  262. ToolTip.BorderColor3 = Color3.new(1, 1, 1)
  263. ToolTip.Size = UDim2.new(0, 200, 0, 50)
  264. ToolTip.ZIndex = 3
  265. ToolTip.Visible = false
  266.  
  267. TextLabel.Parent = ToolTip
  268. TextLabel.BackgroundColor3 = Color3.new(1, 1, 1)
  269. TextLabel.BackgroundTransparency = 1
  270. TextLabel.Position = UDim2.new(0, 2, 0, 2)
  271. TextLabel.Size = UDim2.new(0, 196, 0, 46)
  272. TextLabel.ZIndex = 3
  273. TextLabel.Font = Enum.Font.SourceSans
  274. TextLabel.Text = "This is some slightly longer text."
  275. TextLabel.TextColor3 = Color3.new(1, 1, 1)
  276. TextLabel.TextSize = 14
  277. TextLabel.TextWrapped = true
  278. TextLabel.TextXAlignment = Enum.TextXAlignment.Left
  279. TextLabel.TextYAlignment = Enum.TextYAlignment.Top
  280.  
  281. -------------------------------------------------------------------------------
  282. -- init
  283. local RunService = game:GetService("RunService")
  284. local UserInputService = game:GetService("UserInputService")
  285. local TweenService = game:GetService("TweenService")
  286. local ContentProvider = game:GetService("ContentProvider")
  287. local TextService = game:GetService("TextService")
  288. local Mouse = game:GetService("Players").LocalPlayer:GetMouse()
  289.  
  290. local selectedColor = Color3.new(0.321569, 0.333333, 1)
  291. local deselectedColor = Color3.new(0.8, 0.8, 0.8)
  292. --- So things are descending
  293. local layoutOrderNum = 999999999
  294. --- Whether or not the gui is closing
  295. local mainClosing = false
  296. --- Whether or not the gui is closed (defaults to false)
  297. local closed = false
  298. --- Whether or not the sidebar is closing
  299. local sideClosing = false
  300. --- Whether or not the sidebar is closed (defaults to true but opens automatically on remote selection)
  301. local sideClosed = false
  302. --- Whether or not the code box is maximized (defaults to false)
  303. local maximized = false
  304. --- The event logs to be read from
  305. local logs = {}
  306. --- The event currently selected.Log (defaults to nil)
  307. local selected = nil
  308. --- The blacklist (can be a string name or the Remote Instance)
  309. local blacklist = {}
  310. --- The block list (can be a string name or the Remote Instance)
  311. local blocklist = {}
  312. --- Whether or not to add getNil function
  313. local getNil = false
  314. --- Array of remotes (and original functions) connected to
  315. local connectedRemotes = {}
  316. --- True = hookfunction, false = namecall
  317. local toggle = false
  318. local gm = getrawmetatable(game)
  319. local original = gm.__namecall
  320. setreadonly(gm, false)
  321. --- used to prevent recursives
  322. local prevTables = {}
  323. --- holds logs (for deletion)
  324. local remoteLogs = {}
  325. --- used for hookfunction
  326. local remoteEvent = Instance.new("RemoteEvent")
  327. --- used for hookfunction
  328. local remoteFunction = Instance.new("RemoteFunction")
  329. local originalEvent = remoteEvent.FireServer
  330. local originalFunction = remoteFunction.InvokeServer
  331. --- the maximum amount of remotes allowed in logs
  332. _G.SIMPLESPYCONFIG_MaxRemotes = 500
  333. --- how many spaces to indent
  334. local indent = 4
  335. --- used for task scheduler
  336. local scheduled = {}
  337. --- RBXScriptConnect of the task scheduler
  338. local schedulerconnect
  339. local SimpleSpy = {}
  340. local topstr = ""
  341. local bottomstr = ""
  342. local remotesFadeIn
  343. local rightFadeIn
  344. local codebox
  345. local p
  346. local getnilrequired = false
  347.  
  348. -- autoblock variables
  349. local autoblock = false
  350. local history = {}
  351. local excluding = {}
  352.  
  353. -- function info variables
  354. local funcEnabled = true
  355.  
  356. -- remote hooking/connecting api variables
  357. local remoteSignals = {}
  358. local remoteHooks = {}
  359.  
  360. -- original mouse icon
  361. local oldIcon = Mouse.Icon
  362.  
  363. -- if mouse inside gui
  364. local mouseInGui = false
  365.  
  366. -- handy array of RBXScriptConnections to disconnect on shutdown
  367. local connections = {}
  368.  
  369. -- whether or not SimpleSpy uses 'getcallingscript()' to get the script (default is false because detection)
  370. local useGetCallingScript = false
  371.  
  372. -- functions
  373.  
  374. --- Converts arguments to a string and generates code that calls the specified method with them, recommended to be used in conjunction with ValueToString (method must be a string, e.g. `game:GetService("ReplicatedStorage").Remote:FireServer`)
  375. --- @param method string
  376. --- @param args any[]
  377. --- @return string
  378. function SimpleSpy:ArgsToString(method, args)
  379. assert(typeof(method) == "string", "string expected, got " .. typeof(method))
  380. assert(typeof(args) == "table", "table expected, got " .. typeof(args))
  381. return v2v({args = args}) .. "\n\n" .. method .. "(unpack(args))"
  382. end
  383.  
  384. --- Converts a value to variables with the specified index as the variable name (if nil/invalid then the name will be assigned automatically)
  385. --- @param t any[]
  386. --- @return string
  387. function SimpleSpy:TableToVars(t)
  388. assert(typeof(t) == "table", "table expected, got " .. typeof(t))
  389. return v2v(t)
  390. end
  391.  
  392. --- Converts a value to a variable with the specified `variablename` (if nil/invalid then the name will be assigned automatically)
  393. --- @param value any
  394. --- @return string
  395. function SimpleSpy:ValueToVar(value, variablename)
  396. assert(variablename == nil or typeof(variablename) == "string", "string expected, got " .. typeof(variablename))
  397. if not variablename then
  398. variablename = 1
  399. end
  400. return v2v({[variablename] = value})
  401. end
  402.  
  403. --- Converts any value to a string, cannot preserve function contents
  404. --- @param value any
  405. --- @return string
  406. function SimpleSpy:ValueToString(value)
  407. return v2s(value)
  408. end
  409.  
  410. --- Generates the simplespy function info
  411. --- @param func function
  412. --- @return string
  413. function SimpleSpy:GetFunctionInfo(func)
  414. assert(typeof(func) == "function", "Instance expected, got " .. typeof(func))
  415. return v2v{functionInfo = {
  416. info = debug.getinfo(func),
  417. constants = debug.getconstants(func)
  418. }}
  419. end
  420.  
  421. --- Gets the ScriptSignal for a specified remote being fired
  422. --- @param remote Instance
  423. function SimpleSpy:GetRemoteFiredSignal(remote)
  424. assert(typeof(remote) == "Instance", "Instance expected, got " .. typeof(remote))
  425. if not remoteSignals[remote] then
  426. remoteSignals[remote] = newSignal()
  427. end
  428. return remoteSignals[remote]
  429. end
  430.  
  431. --- Allows for direct hooking of remotes **THIS CAN BE VERY DANGEROUS**
  432. --- @param remote Instance
  433. --- @param f function
  434. function SimpleSpy:HookRemote(remote, f)
  435. assert(typeof(remote) == "Instance", "Instance expected, got " .. typeof(remote))
  436. assert(typeof(f) == "function", "function expected, got " .. typeof(f))
  437. remoteHooks[remote] = f
  438. end
  439.  
  440. --- Blocks the specified remote instance/string
  441. --- @param remote any
  442. function SimpleSpy:BlockRemote(remote)
  443. assert(typeof(remote) == "Instance" or typeof(remote) == "string", "Instance | string expected, got " .. typeof(remote))
  444. blocklist[remote] = true
  445. end
  446.  
  447. --- Excludes the specified remote from logs (instance/string)
  448. --- @param remote any
  449. function SimpleSpy:ExcludeRemote(remote)
  450. assert(typeof(remote) == "Instance" or typeof(remote) == "string", "Instance | string expected, got " .. typeof(remote))
  451. blacklist[remote] = true
  452. end
  453.  
  454. --- Creates a new ScriptSignal that can be connected to and fired
  455. --- @return table
  456. function newSignal()
  457. local connected = {}
  458. return {
  459. Connect = function(self, f)
  460. assert(connected, "Signal is closed")
  461. connected[tostring(f)] = f
  462. return setmetatable({
  463. Connected = true,
  464. Disconnect = function(self)
  465. if not connected then
  466. warn("Signal is already closed")
  467. end
  468. self.Connected = false
  469. connected[tostring(f)] = nil
  470. end
  471. },
  472. {
  473. __index = function(self, i)
  474. if i == "Connected" then
  475. return not not connected[tostring(f)]
  476. end
  477. end
  478. })
  479. end,
  480. Fire = function(self, ...)
  481. for _, f in pairs(connected) do
  482. coroutine.wrap(f)(...)
  483. end
  484. end
  485. }
  486. end
  487.  
  488. --- Prevents remote spam from causing lag (clears logs after `_G.SIMPLESPYCONFIG_MaxRemotes` or 500 remotes)
  489. function clean()
  490. local max = _G.SIMPLESPYCONFIG_MaxRemotes
  491. if not typeof(max) == "number" and math.floor(max) ~= max then
  492. max = 500
  493. end
  494. if #remoteLogs > max then
  495. for i = 100, #remoteLogs do
  496. local v = remoteLogs[i]
  497. if typeof(v[1]) == "RBXScriptConnection" then
  498. v[1]:Disconnect()
  499. end
  500. if typeof(v[2]) == "Instance" then
  501. v[2]:Destroy()
  502. end
  503. end
  504. local newLogs = {}
  505. for i = 1, 100 do
  506. table.insert(newLogs, remoteLogs[i])
  507. end
  508. remoteLogs = newLogs
  509. end
  510. end
  511.  
  512. --- Scales the ToolTip to fit containing text
  513. function scaleToolTip()
  514. local size = TextService:GetTextSize(TextLabel.Text, TextLabel.TextSize, TextLabel.Font, Vector2.new(196, math.huge))
  515. TextLabel.Size = UDim2.new(0, size.X, 0, size.Y)
  516. ToolTip.Size = UDim2.new(0, size.X + 4, 0, size.Y + 4)
  517. end
  518.  
  519. --- Executed when the toggle button (the SimpleSpy logo) is hovered over
  520. function onToggleButtonHover()
  521. if not toggle then
  522. TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(252, 51, 51)}):Play()
  523. else
  524. TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(68, 206, 91)}):Play()
  525. end
  526. end
  527.  
  528. --- Executed when the toggle button is unhovered over
  529. function onToggleButtonUnhover()
  530. TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(255, 255, 255)}):Play()
  531. end
  532.  
  533. --- Executed when the X button is hovered over
  534. function onXButtonHover()
  535. TweenService:Create(CloseButton, TweenInfo.new(0.2), {BackgroundColor3 = Color3.fromRGB(255, 60, 60)}):Play()
  536. end
  537.  
  538. --- Executed when the X button is unhovered over
  539. function onXButtonUnhover()
  540. TweenService:Create(CloseButton, TweenInfo.new(0.2), {BackgroundColor3 = Color3.fromRGB(37, 36, 38)}):Play()
  541. end
  542.  
  543. --- Toggles the remote spy method (when button clicked)
  544. function onToggleButtonClick()
  545. if toggle then
  546. TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(252, 51, 51)}):Play()
  547. else
  548. TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(68, 206, 91)}):Play()
  549. end
  550. toggleSpyMethod()
  551. end
  552.  
  553. --- Reconnects bringBackOnResize if the current viewport changes and also connects it initially
  554. function connectResize()
  555. local lastCam = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(bringBackOnResize)
  556. workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
  557. lastCam:Disconnect()
  558. if workspace.CurrentCamera then
  559. lastCam = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(bringBackOnResize)
  560. end
  561. end)
  562. end
  563.  
  564. --- Brings gui back if it gets lost offscreen (connected to the camera viewport changing)
  565. function bringBackOnResize()
  566. local currentX = Background.AbsolutePosition.X
  567. local currentY = Background.AbsolutePosition.Y
  568. local viewportSize = workspace.CurrentCamera.ViewportSize
  569. if (currentX < 0) or (currentX > (viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X))) then
  570. if currentX < 0 then
  571. currentX = 0
  572. else
  573. currentX = viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)
  574. end
  575. end
  576. if (currentY < 0) or (currentY > (viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36)) then
  577. if currentY < 0 then
  578. currentY = 0
  579. else
  580. currentY = viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36
  581. end
  582. end
  583. TweenService.Create(TweenService, Background, TweenInfo.new(0.1), {Position = UDim2.new(0, currentX, 0, currentY)}):Play()
  584. end
  585.  
  586. --- Drags gui (so long as mouse is held down)
  587. function onBarInput(input)
  588. if input.UserInputType == Enum.UserInputType.MouseButton1 then
  589. local lastPos = UserInputService.GetMouseLocation(UserInputService)
  590. local mainPos = Background.AbsolutePosition
  591. local offset = mainPos - lastPos
  592. local currentPos = offset + lastPos
  593. RunService.BindToRenderStep(RunService, "drag", 1,
  594. function()
  595. local newPos = UserInputService.GetMouseLocation(UserInputService)
  596. if newPos ~= lastPos then
  597. local currentX = (offset + newPos).X
  598. local currentY = (offset + newPos).Y
  599. local viewportSize = workspace.CurrentCamera.ViewportSize
  600. if (currentX < 0 and currentX < currentPos.X) or (currentX > (viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)) and currentX > currentPos.X) then
  601. if currentX < 0 then
  602. currentX = 0
  603. else
  604. currentX = viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)
  605. end
  606. end
  607. if (currentY < 0 and currentY < currentPos.Y) or (currentY > (viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36) and currentY > currentPos.Y) then
  608. if currentY < 0 then
  609. currentY = 0
  610. else
  611. currentY = viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36
  612. end
  613. end
  614. currentPos = Vector2.new(currentX, currentY)
  615. lastPos = newPos
  616. TweenService.Create(TweenService, Background, TweenInfo.new(0.1), {Position = UDim2.new(0, currentPos.X, 0, currentPos.Y)}):Play()
  617. end
  618. if not UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) then
  619. RunService.UnbindFromRenderStep(RunService, "drag")
  620. end
  621. end
  622. )
  623. end
  624. end
  625.  
  626. --- Fades out the table of elements (and makes them invisible), returns a function to make them visible again
  627. function fadeOut(elements)
  628. local data = {}
  629. for _, v in pairs(elements) do
  630. if typeof(v) == "Instance" and v:IsA("GuiObject") and v.Visible then
  631. coroutine.wrap(function()
  632. data[v] = {
  633. BackgroundTransparency = v.BackgroundTransparency
  634. }
  635. TweenService:Create(v, TweenInfo.new(0.5), {BackgroundTransparency = 1}):Play()
  636. if v:IsA("TextBox") or v:IsA("TextButton") or v:IsA("TextLabel") then
  637. data[v].TextTransparency = v.TextTransparency
  638. TweenService:Create(v, TweenInfo.new(0.5), {TextTransparency = 1}):Play()
  639. elseif v:IsA("ImageButton") or v:IsA("ImageLabel") then
  640. data[v].ImageTransparency = v.ImageTransparency
  641. TweenService:Create(v, TweenInfo.new(0.5), {ImageTransparency = 1}):Play()
  642. end
  643. wait(0.5)
  644. v.Visible = false
  645. for i, x in pairs(data[v]) do
  646. v[i] = x
  647. end
  648. data[v] = true
  649. end)()
  650. end
  651. end
  652. return function()
  653. for i, _ in pairs(data) do
  654. coroutine.wrap(function()
  655. local properties = {
  656. BackgroundTransparency = i.BackgroundTransparency
  657. }
  658. i.BackgroundTransparency = 1
  659. TweenService:Create(i, TweenInfo.new(0.5), {BackgroundTransparency = properties.BackgroundTransparency}):Play()
  660. if i:IsA("TextBox") or i:IsA("TextButton") or i:IsA("TextLabel") then
  661. properties.TextTransparency = i.TextTransparency
  662. i.TextTransparency = 1
  663. TweenService:Create(i, TweenInfo.new(0.5), {TextTransparency = properties.TextTransparency}):Play()
  664. elseif i:IsA("ImageButton") or i:IsA("ImageLabel") then
  665. properties.ImageTransparency = i.ImageTransparency
  666. i.ImageTransparency = 1
  667. TweenService:Create(i, TweenInfo.new(0.5), {ImageTransparency = properties.ImageTransparency}):Play()
  668. end
  669. i.Visible = true
  670. end)()
  671. end
  672. end
  673. end
  674.  
  675. --- Expands and minimizes the gui (closed is the toggle boolean)
  676. function toggleMinimize(override)
  677. if mainClosing and not override or maximized then
  678. return
  679. end
  680. mainClosing = true
  681. closed = not closed
  682. if closed then
  683. if not sideClosed then
  684. toggleSideTray(true)
  685. end
  686. LeftPanel.Visible = true
  687. TweenService:Create(LeftPanel, TweenInfo.new(0.5), {Size = UDim2.new(0, 131, 0, 0)}):Play()
  688. wait(0.5)
  689. remotesFadeIn = fadeOut(LeftPanel:GetDescendants())
  690. wait(0.5)
  691. else
  692. TweenService:Create(LeftPanel, TweenInfo.new(0.5), {Size = UDim2.new(0, 131, 0, 249)}):Play()
  693. wait(0.5)
  694. if remotesFadeIn then
  695. remotesFadeIn()
  696. remotesFadeIn = nil
  697. end
  698. bringBackOnResize()
  699. end
  700. mainClosing = false
  701. end
  702.  
  703. --- Expands and minimizes the sidebar (sideClosed is the toggle boolean)
  704. function toggleSideTray(override)
  705. if sideClosing and not override or maximized then
  706. return
  707. end
  708. sideClosing = true
  709. sideClosed = not sideClosed
  710. if sideClosed then
  711. rightFadeIn = fadeOut(RightPanel:GetDescendants())
  712. wait(0.5)
  713. minimizeSize(0.5)
  714. wait(0.5)
  715. RightPanel.Visible = false
  716. else
  717. if closed then
  718. toggleMinimize(true)
  719. end
  720. RightPanel.Visible = true
  721. maximizeSize(0.5)
  722. wait(0.5)
  723. if rightFadeIn then
  724. rightFadeIn()
  725. end
  726. bringBackOnResize()
  727. end
  728. sideClosing = false
  729. end
  730.  
  731. --- Expands code box to fit screen for more convenient viewing
  732. function toggleMaximize()
  733. if not sideClosed and not maximized then
  734. maximized = true
  735. local disable = Instance.new("TextButton")
  736. local prevSize = UDim2.new(0, CodeBox.AbsoluteSize.X, 0, CodeBox.AbsoluteSize.Y)
  737. local prevPos = UDim2.new(0,CodeBox.AbsolutePosition.X, 0, CodeBox.AbsolutePosition.Y)
  738. disable.Size = UDim2.new(1, 0, 1, 0)
  739. disable.BackgroundColor3 = Color3.new()
  740. disable.BorderSizePixel = 0
  741. disable.Text = 0
  742. disable.ZIndex = 3
  743. disable.BackgroundTransparency = 1
  744. disable.AutoButtonColor = false
  745. CodeBox.ZIndex = 4
  746. CodeBox.Position = prevPos
  747. CodeBox.Size = prevSize
  748. TweenService:Create(CodeBox, TweenInfo.new(0.5), {Size = UDim2.new(0.5, 0, 0.5, 0), Position = UDim2.new(0.25, 0, 0.25, 0)}):Play()
  749. TweenService:Create(disable, TweenInfo.new(0.5), {BackgroundTransparency = 0.5}):Play()
  750. disable.MouseButton1Click:Connect(function()
  751. if UserInputService:GetMouseLocation().Y + 36 >= CodeBox.AbsolutePosition.Y and UserInputService:GetMouseLocation().Y + 36 <= CodeBox.AbsolutePosition.Y + CodeBox.AbsoluteSize.Y
  752. and UserInputService:GetMouseLocation().X >= CodeBox.AbsolutePosition.X and UserInputService:GetMouseLocation().X <= CodeBox.AbsolutePosition.X + CodeBox.AbsoluteSize.X then
  753. return
  754. end
  755. TweenService:Create(CodeBox, TweenInfo.new(0.5), {Size = prevSize, Position = prevPos}):Play()
  756. TweenService:Create(disable, TweenInfo.new(0.5), {BackgroundTransparency = 1}):Play()
  757. wait(0.5)
  758. disable:Destroy()
  759. CodeBox.Size = UDim2.new(1, 0, 0.5, 0)
  760. CodeBox.Position = UDim2.new(0, 0, 0, 0)
  761. CodeBox.ZIndex = 0
  762. maximized = false
  763. end)
  764. end
  765. end
  766.  
  767. --- Checks if cursor is within resize range
  768. --- @param p Vector2
  769. function isInResizeRange(p)
  770. local relativeP = p - Background.AbsolutePosition
  771. local range = 5
  772. if relativeP.X >= TopBar.AbsoluteSize.X - range and relativeP.Y >= Background.AbsoluteSize.Y - range
  773. and relativeP.X <= TopBar.AbsoluteSize.X and relativeP.Y <= Background.AbsoluteSize.Y then
  774. return true, 'B'
  775. elseif relativeP.X >= TopBar.AbsoluteSize.X - range and relativeP.X <= Background.AbsoluteSize.X then
  776. return true, 'X'
  777. elseif relativeP.Y >= Background.AbsoluteSize.Y - range and relativeP.Y <= Background.AbsoluteSize.Y then
  778. return true, 'Y'
  779. end
  780. return false
  781. end
  782.  
  783. --- Called when mouse enters SimpleSpy
  784. function mouseEntered()
  785. local customCursor = Instance.new("ImageLabel")
  786. customCursor.Size = UDim2.fromOffset(200, 200)
  787. customCursor.ZIndex = 1e5
  788. customCursor.BackgroundTransparency = 1
  789. customCursor.Image = ""
  790. customCursor.Parent = SimpleSpy2
  791. UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceHide
  792. RunService:BindToRenderStep("SIMPLESPY_CURSOR", 1, function()
  793. if mouseInGui and _G.SimpleSpyExecuted then
  794. local mouseLocation = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
  795. customCursor.Position = UDim2.fromOffset(mouseLocation.X - customCursor.AbsoluteSize.X / 2, mouseLocation.Y - customCursor.AbsoluteSize.Y / 2)
  796. local inRange, type = isInResizeRange(mouseLocation)
  797. if inRange and not sideClosed and not closed then
  798. customCursor.Image = type == 'B' and "rbxassetid://6065821980" or type == 'X' and "rbxassetid://6065821086" or type == 'Y' and "rbxassetid://6065821596"
  799. elseif inRange and not closed and type == 'Y' or type == 'B' then
  800. customCursor.Image = "rbxassetid://6065821596"
  801. elseif customCursor.Image ~= "rbxassetid://6065775281" then
  802. customCursor.Image = "rbxassetid://6065775281"
  803. end
  804. else
  805. UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.None
  806. customCursor:Destroy()
  807. RunService:UnbindFromRenderStep("SIMPLESPY_CURSOR")
  808. end
  809. end)
  810. end
  811.  
  812. --- Called when mouse moves
  813. function mouseMoved()
  814. local mousePos = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
  815. if not closed
  816. and mousePos.X >= TopBar.AbsolutePosition.X and mousePos.X <= TopBar.AbsolutePosition.X + TopBar.AbsoluteSize.X
  817. and mousePos.Y >= Background.AbsolutePosition.Y and mousePos.Y <= Background.AbsolutePosition.Y + Background.AbsoluteSize.Y then
  818. if not mouseInGui then
  819. mouseInGui = true
  820. mouseEntered()
  821. end
  822. else
  823. mouseInGui = false
  824. end
  825. end
  826.  
  827. --- Adjusts the ui elements to the 'Maximized' size
  828. function maximizeSize(speed)
  829. if not speed then
  830. speed = 0.05
  831. end
  832. TweenService:Create(LeftPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
  833. TweenService:Create(RightPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
  834. TweenService:Create(TopBar, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X, TopBar.AbsoluteSize.Y) }):Play()
  835. TweenService:Create(ScrollingFrame, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, 110), Position = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
  836. TweenService:Create(CodeBox, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
  837. TweenService:Create(LogList, TweenInfo.new(speed), { Size = UDim2.fromOffset(LogList.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y - 18) }):Play()
  838. end
  839.  
  840. --- Adjusts the ui elements to close the side
  841. function minimizeSize(speed)
  842. if not speed then
  843. speed = 0.05
  844. end
  845. TweenService:Create(LeftPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
  846. TweenService:Create(RightPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(0, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
  847. TweenService:Create(TopBar, TweenInfo.new(speed), { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, TopBar.AbsoluteSize.Y) }):Play()
  848. TweenService:Create(ScrollingFrame, TweenInfo.new(speed), { Size = UDim2.fromOffset(0, 119), Position = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
  849. TweenService:Create(CodeBox, TweenInfo.new(speed), { Size = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
  850. TweenService:Create(LogList, TweenInfo.new(speed), { Size = UDim2.fromOffset(LogList.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y - 18) }):Play()
  851. end
  852.  
  853. --- Called on user input while mouse in 'Background' frame
  854. --- @param input InputObject
  855. function backgroundUserInput(input)
  856. local inRange, type = isInResizeRange(UserInputService:GetMouseLocation() - Vector2.new(0, 36))
  857. if input.UserInputType == Enum.UserInputType.MouseButton1 and inRange then
  858. local lastPos = UserInputService:GetMouseLocation()
  859. local offset = Background.AbsoluteSize - lastPos
  860. local currentPos = lastPos + offset
  861. RunService:BindToRenderStep("SIMPLESPY_RESIZE", 1, function()
  862. local newPos = UserInputService:GetMouseLocation()
  863. if newPos ~= lastPos then
  864. local currentX = (newPos + offset).X
  865. local currentY = (newPos + offset).Y
  866. if currentX < 450 then
  867. currentX = 450
  868. end
  869. if currentY < 268 then
  870. currentY = 268
  871. end
  872. currentPos = Vector2.new(currentX, currentY)
  873. Background.Size = UDim2.fromOffset((not sideClosed and not closed and (type == "X" or type == "B")) and currentPos.X or Background.AbsoluteSize.X, (--[[(not sideClosed or currentPos.X <= LeftPanel.AbsolutePosition.X + LeftPanel.AbsoluteSize.X) and]] not closed and (type == "Y" or type == "B")) and currentPos.Y or Background.AbsoluteSize.Y)
  874. if sideClosed then
  875. minimizeSize()
  876. else
  877. maximizeSize()
  878. end
  879. lastPos = newPos
  880. end
  881. end)
  882. table.insert(connections, UserInputService.InputEnded:Connect(function(inputE)
  883. if input == inputE then
  884. RunService:UnbindFromRenderStep("SIMPLESPY_RESIZE")
  885. end
  886. end))
  887. end
  888. end
  889.  
  890. --- Gets the player an instance is descended from
  891. function getPlayerFromInstance(instance)
  892. for _, v in pairs(Players:GetPlayers()) do
  893. if v.Character and (instance:IsDescendantOf(v.Character) or instance == v.Character) then
  894. return v
  895. end
  896. end
  897. end
  898.  
  899. --- Runs on MouseButton1Click of an event frame
  900. function eventSelect(frame)
  901. if selected and selected.Log then
  902. TweenService:Create(selected.Log.Button, TweenInfo.new(0.5), {BackgroundColor3 = Color3.fromRGB(0, 0, 0)}):Play()
  903. selected = nil
  904. end
  905. for _, v in pairs(logs) do
  906. if frame == v.Log then
  907. selected = v
  908. end
  909. end
  910. if selected and selected.Log then
  911. TweenService:Create(frame.Button, TweenInfo.new(0.5), {BackgroundColor3 = Color3.fromRGB(92, 126, 229)}):Play()
  912. codebox:setRaw(selected.GenScript)
  913. end
  914. if sideClosed then
  915. toggleSideTray()
  916. end
  917. end
  918.  
  919. --- Updates the canvas size to fit the current amount of function buttons
  920. function updateFunctionCanvas()
  921. ScrollingFrame.CanvasSize = UDim2.fromOffset(UIGridLayout.AbsoluteContentSize.X, UIGridLayout.AbsoluteContentSize.Y)
  922. end
  923.  
  924. --- Updates the canvas size to fit the amount of current remotes
  925. function updateRemoteCanvas()
  926. LogList.CanvasSize = UDim2.fromOffset(UIListLayout.AbsoluteContentSize.X, UIListLayout.AbsoluteContentSize.Y)
  927. end
  928.  
  929. --- Allows for toggling of the tooltip and easy setting of le description
  930. --- @param enable boolean
  931. --- @param text string
  932. function makeToolTip(enable, text)
  933. if enable then
  934. if ToolTip.Visible then
  935. ToolTip.Visible = false
  936. RunService:UnbindFromRenderStep("ToolTip")
  937. end
  938. local first = true
  939. RunService:BindToRenderStep("ToolTip", 1, function()
  940. local topLeft = Vector2.new(Mouse.X + 20, Mouse.Y + 20)
  941. local bottomRight = topLeft + ToolTip.AbsoluteSize
  942. if topLeft.X < 0 then
  943. topLeft = Vector2.new(0, topLeft.Y)
  944. elseif bottomRight.X > workspace.CurrentCamera.ViewportSize.X then
  945. topLeft = Vector2.new(workspace.CurrentCamera.ViewportSize.X - ToolTip.AbsoluteSize.X, topLeft.Y)
  946. end
  947. if topLeft.Y < 0 then
  948. topLeft = Vector2.new(topLeft.X, 0)
  949. elseif bottomRight.Y > workspace.CurrentCamera.ViewportSize.Y - 35 then
  950. topLeft = Vector2.new(topLeft.X, workspace.CurrentCamera.ViewportSize.Y - ToolTip.AbsoluteSize.Y - 35)
  951. end
  952. if topLeft.X <= Mouse.X and topLeft.Y <= Mouse.Y then
  953. topLeft = Vector2.new(Mouse.X - ToolTip.AbsoluteSize.X - 2, Mouse.Y - ToolTip.AbsoluteSize.Y - 2)
  954. end
  955. if first then
  956. ToolTip.Position = UDim2.fromOffset(topLeft.X, topLeft.Y)
  957. first = false
  958. else
  959. ToolTip:TweenPosition(UDim2.fromOffset(topLeft.X, topLeft.Y), "Out", "Linear", 0.1)
  960. end
  961. end)
  962. TextLabel.Text = text
  963. ToolTip.Visible = true
  964. else
  965. if ToolTip.Visible then
  966. ToolTip.Visible = false
  967. RunService:UnbindFromRenderStep("ToolTip")
  968. end
  969. end
  970. end
  971.  
  972. --- Creates new function button (below codebox)
  973. --- @param name string
  974. ---@param description function
  975. ---@param onClick function
  976. function newButton(name, description, onClick)
  977. local button = FunctionTemplate:Clone()
  978. button.Text.Text = name
  979. button.Button.MouseEnter:Connect(function()
  980. makeToolTip(true, description())
  981. end)
  982. button.Button.MouseLeave:Connect(function()
  983. makeToolTip(false)
  984. end)
  985. button.AncestryChanged:Connect(function()
  986. makeToolTip(false)
  987. end)
  988. button.Button.MouseButton1Click:Connect(function(...)
  989. onClick(button, ...)
  990. end)
  991. button.Parent = ScrollingFrame
  992. updateFunctionCanvas()
  993. end
  994.  
  995. --- Adds new Remote to logs
  996. --- @param name string The name of the remote being logged
  997. --- @param type string The type of the remote being logged (either 'function' or 'event')
  998. --- @param gen_script any
  999. --- @param remote any
  1000. --- @param function_info string
  1001. --- @param blocked any
  1002. function newRemote(type, name, gen_script, remote, function_info, blocked, src)
  1003. local remoteFrame = RemoteTemplate:Clone()
  1004. remoteFrame.Text.Text = name
  1005. remoteFrame.ColorBar.BackgroundColor3 = type == "event" and Color3.new(255, 242, 0) or Color3.fromRGB(99, 86, 245)
  1006. local id = Instance.new("IntValue")
  1007. id.Name = "ID"
  1008. id.Value = #logs + 1
  1009. id.Parent = remoteFrame
  1010. logs[#logs + 1] = {
  1011. Name = name,
  1012. GenScript = gen_script,
  1013. Function = function_info,
  1014. Remote = remote,
  1015. Log = remoteFrame,
  1016. Blocked = blocked,
  1017. Source = src
  1018. }
  1019. if blocked then
  1020. logs[#logs].GenScript = "-- THIS REMOTE WAS PREVENTED FROM FIRING THE SERVER BY SIMPLESPY\n\n" .. logs[#logs].GenScript
  1021. end
  1022. local connect = remoteFrame.Button.MouseButton1Click:Connect(function()
  1023. eventSelect(remoteFrame)
  1024. end)
  1025. if layoutOrderNum < 1 then
  1026. layoutOrderNum = 999999999
  1027. end
  1028. remoteFrame.LayoutOrder = layoutOrderNum
  1029. layoutOrderNum = layoutOrderNum - 1
  1030. remoteFrame.Parent = LogList
  1031. table.insert(remoteLogs, 1, {connect, remoteFrame})
  1032. clean()
  1033. updateRemoteCanvas()
  1034. end
  1035.  
  1036. --- Generates a script from the provided arguments (first has to be remote path)
  1037. function genScript(remote, ...)
  1038. prevTables = {}
  1039. local gen = ""
  1040. local args = {...}
  1041. if #args > 0 then
  1042. if not pcall(function()
  1043. gen = v2v({args = args}) .. "\n"
  1044. end)
  1045. then
  1046. gen = gen .. "-- TableToString failure! Reverting to legacy functionality (results may vary)\nlocal args = {"
  1047. if
  1048. not pcall(
  1049. function()
  1050. for i, v in pairs(args) do
  1051. if type(i) ~= "Instance" and type(i) ~= "userdata" then
  1052. gen = gen .. "\n [" .. tostring(i) .. "] = "
  1053. elseif type(i) == "string" then
  1054. gen = gen .. '\n ["' .. tostring(i) .. '"] = '
  1055. elseif type(i) == "userdata" and typeof(i) ~= "Instance" then
  1056. gen = gen .. "\n [" .. typeof(i) .. ".new(" .. tostring(i) .. ")] = "
  1057. elseif type(i) == "userdata" then
  1058. gen = gen .. "\n [game." .. i:GetFullName() .. ")] = "
  1059. end
  1060. if type(v) ~= "Instance" and type(v) ~= "userdata" then
  1061. gen = gen .. tostring(v)
  1062. elseif type(v) == "string" then
  1063. gen = gen .. '"' .. tostring(v) .. '"'
  1064. elseif type(v) == "userdata" and typeof(v) ~= "Instance" then
  1065. gen = gen .. typeof(v) .. ".new(" .. tostring(v) .. ")"
  1066. elseif type(v) == "userdata" then
  1067. gen = gen .. "game." .. v:GetFullName()
  1068. end
  1069. end
  1070. gen = gen .. "\n}\n\n"
  1071. end
  1072. )
  1073. then
  1074. gen = gen .. "}\n-- Legacy tableToString failure! Unable to decompile."
  1075. end
  1076. end
  1077. if not remote:IsDescendantOf(game) and not getnilrequired then
  1078. gen = "function getNil(name,class) for _,v in pairs(getnilinstances())do if v.ClassName==class and v.Name==name then return v;end end end\n\n" .. gen
  1079. end
  1080. if remote:IsA("RemoteEvent") then
  1081. gen = gen .. v2s(remote) .. ":FireServer(unpack(args))"
  1082. elseif remote:IsA("RemoteFunction") then
  1083. gen = gen .. v2s(remote) .. ":InvokeServer(unpack(args))"
  1084. end
  1085. else
  1086. if remote:IsA("RemoteEvent") then
  1087. gen = gen .. v2s(remote) .. ":FireServer()"
  1088. elseif remote:IsA("RemoteFunction") then
  1089. gen = gen .. v2s(remote) .. ":InvokeServer()"
  1090. end
  1091. end
  1092. gen = "" .. gen
  1093. prevTables = {}
  1094. return gen
  1095. end
  1096.  
  1097. --- value-to-string: value, string (out), level (indentation), parent table, var name, is from tovar
  1098. function v2s(v, l, p, n, vtv, i, pt, path, tables)
  1099. if typeof(v) == "number" then
  1100. if v == math.huge then
  1101. return "math.huge"
  1102. elseif tostring(v):match("nan") then
  1103. return "0/0 --[[NaN]]"
  1104. end
  1105. return tostring(v)
  1106. elseif typeof(v) == "boolean" then
  1107. return tostring(v)
  1108. elseif typeof(v) == "string" then
  1109. return formatstr(v)
  1110. elseif typeof(v) == "function" then
  1111. return f2s(v)
  1112. elseif typeof(v) == "table" then
  1113. return t2s(v, l, p, n, vtv, i, pt, path, tables)
  1114. elseif typeof(v) == "Instance" then
  1115. return i2p(v)
  1116. elseif typeof(v) == "userdata" then
  1117. return "newproxy(true)"
  1118. elseif type(v) == "userdata" then
  1119. return u2s(v)
  1120. else
  1121. return "nil --[[" .. typeof(v) .. "]]"
  1122. end
  1123. end
  1124.  
  1125. --- value-to-variable
  1126. --- @param t any
  1127. function v2v(t)
  1128. topstr = ""
  1129. bottomstr = ""
  1130. getnilrequired = false
  1131. local ret = ""
  1132. local count = 1
  1133. for i, v in pairs(t) do
  1134. if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
  1135. ret = ret .. "local " .. i .. " = " .. v2s(v, nil, nil, i, true) .. "\n"
  1136. elseif tostring(i):match("^[%a_]+[%w_]*$") then
  1137. ret = ret .. "local " .. tostring(i):lower() .. "_" .. tostring(count) .. " = " .. v2s(v, nil, nil, tostring(i):lower() .. "_" .. tostring(count), true) .. "\n"
  1138. else
  1139. ret = ret .. "local " .. type(v) .. "_" .. tostring(count) .. " = " .. v2s(v, nil, nil, type(v) .. "_" .. tostring(count), true) .. "\n"
  1140. end
  1141. count = count + 1
  1142. end
  1143. if getnilrequired then
  1144. topstr = "function getNil(name,class) for _,v in pairs(getnilinstances())do if v.ClassName==class and v.Name==name then return v;end end end\n" .. topstr
  1145. end
  1146. if #topstr > 0 then
  1147. ret = topstr .. "\n" .. ret
  1148. end
  1149. if #bottomstr > 0 then
  1150. ret = ret .. bottomstr
  1151. end
  1152. return ret
  1153. end
  1154.  
  1155. --- table-to-string
  1156. --- @param t table
  1157. --- @param l number
  1158. --- @param p table
  1159. --- @param n string
  1160. --- @param vtv boolean
  1161. --- @param i any
  1162. --- @param pt table
  1163. --- @param path string
  1164. --- @param tables table
  1165. function t2s(t, l, p, n, vtv, i, pt, path, tables)
  1166. for k, x in pairs(getrenv()) do
  1167. local isgucci, gpath
  1168. if rawequal(x, t) then
  1169. isgucci, gpath = true, ""
  1170. elseif type(x) == "table" then
  1171. isgucci, gpath = v2p(t, x)
  1172. end
  1173. if isgucci then
  1174. if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
  1175. return k .. gpath
  1176. else
  1177. return "getrenv()[" .. v2s(k) .. "]" .. gpath
  1178. end
  1179. end
  1180. end
  1181. if not path then
  1182. path = ""
  1183. end
  1184. if not l then
  1185. l = 0
  1186. tables = {}
  1187. end
  1188. if not p then
  1189. p = t
  1190. end
  1191. for _, v in pairs(tables) do
  1192. if n and rawequal(v, t) then
  1193. bottomstr = bottomstr .. "\n" .. tostring(n) .. tostring(path) .. " = " .. tostring(n) .. tostring(({v2p(v, p)})[2])
  1194. return "{} --[[DUPLICATE]]"
  1195. end
  1196. end
  1197. table.insert(tables, t)
  1198. local s = "{"
  1199. local size = 0
  1200. l = l + indent
  1201. for k, v in pairs(t) do
  1202. size = size + 1
  1203. if size > (_G.SimpleSpyMaxTableSize and _G.SimpleSpyMaxTableSize or 1000) then
  1204. break
  1205. end
  1206. if rawequal(k, t) then
  1207. bottomstr = bottomstr .. "\n" .. tostring(n) .. tostring(path) .. "[" .. tostring(n) .. tostring(path) .. "]" .. " = " .. (v == k and tostring(n) .. tostring(path) or v2s(v, l, p, n, vtv, k, t, path .. "[" .. tostring(n) .. tostring(path) .. "]", tables))
  1208. size -= 1
  1209. continue
  1210. end
  1211. local currentPath = ""
  1212. if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
  1213. currentPath = "." .. k
  1214. else
  1215. currentPath = "[" .. v2s(k, nil, p, n, vtv, i, pt, path) .. "]"
  1216. end
  1217. s = s .. "\n" .. string.rep(" ", l) .. "[" .. v2s(k, l, p, n, vtv, k, t, path .. currentPath, tables) .. "] = " .. v2s(v, l, p, n, vtv, k, t, path .. currentPath, tables) .. ","
  1218. end
  1219. if #s > 1 then
  1220. s = s:sub(1, #s - 1)
  1221. end
  1222. if size > 0 then
  1223. s = s .. "\n" .. string.rep(" ", l - indent)
  1224. end
  1225. return s .. "}"
  1226. end
  1227.  
  1228. --- function-to-string
  1229. function f2s(f)
  1230. for k, x in pairs(getgenv()) do
  1231. local isgucci, gpath
  1232. if rawequal(x, f) then
  1233. isgucci, gpath = true, ""
  1234. elseif type(x) == "table" then
  1235. isgucci, gpath = v2p(f, x)
  1236. end
  1237. if isgucci then
  1238. if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
  1239. return k .. gpath
  1240. else
  1241. return "getgenv()[" .. v2s(k) .. "]" .. gpath
  1242. end
  1243. end
  1244. end
  1245. -- uwu some cool stuff here once bork finishes up
  1246. -- if SimpleSpy.GetExternalLoader then
  1247. -- local ExternalLoader = SimpleSpy:GetExternalLoader()
  1248. -- local loaded, path = pcall(function() ExternalLoader:LoadAsset("Bork_Functions") end)
  1249. -- if loaded then
  1250. -- local functions = loadfile(path .. "functions.lua")
  1251. -- local out = functions[f]
  1252. -- if out then
  1253. -- return out
  1254. -- end
  1255. -- end
  1256. -- end
  1257. -- local isgucci, gpath = v2p(f, getgc())
  1258. -- if isgucci then
  1259. -- return "getgc()" .. gpath
  1260. -- end
  1261. if debug.getinfo(f).name:match("^[%a_]+[%w_]*$") then
  1262. return "function()end --[[" .. debug.getinfo(f).name .. "]]"
  1263. end
  1264. return "function()end --[[" .. tostring(f) .. "]]"
  1265. end
  1266.  
  1267. --- instance-to-path
  1268. --- @param i userdata
  1269. function i2p(i)
  1270. local player = getplayer(i)
  1271. local parent = i
  1272. local out = ""
  1273. if parent == nil then
  1274. return "nil"
  1275. elseif player then
  1276. while true do
  1277. if parent and parent == player.Character then
  1278. if player == Players.LocalPlayer then
  1279. return 'game:GetService("Players").LocalPlayer.Character' .. out
  1280. else
  1281. return i2p(player) .. ".Character" .. out
  1282. end
  1283. else
  1284. if parent.Name:match("[%a_]+[%w+]*") ~= parent.Name then
  1285. out = '[' .. formatstr(parent.Name) .. ']' .. out
  1286. else
  1287. out = "." .. parent.Name .. out
  1288. end
  1289. end
  1290. parent = parent.Parent
  1291. end
  1292. elseif parent ~= game then
  1293. while true do
  1294. if parent and parent.Parent == game then
  1295. if game:GetService(parent.ClassName) then
  1296. if parent.ClassName == "Workspace" then
  1297. return "workspace" .. out
  1298. else
  1299. return 'game:GetService("' .. parent.ClassName .. '")' .. out
  1300. end
  1301. else
  1302. if parent.Name:match("[%a_]+[%w_]*") then
  1303. return "game." .. parent.Name .. out
  1304. else
  1305. return 'game[' .. formatstr(parent.Name) .. ']' .. out
  1306. end
  1307. end
  1308. elseif parent.Parent == nil then
  1309. getnilrequired = true
  1310. return 'getNil(' .. formatstr(parent.Name) .. ', "' .. parent.ClassName .. '")' .. out
  1311. elseif parent == Players.LocalPlayer then
  1312. out = ".LocalPlayer" .. out
  1313. else
  1314. if parent.Name:match("[%a_]+[%w_]*") ~= parent.Name then
  1315. out = '[' .. formatstr(parent.Name) .. ']' .. out
  1316. else
  1317. out = "." .. parent.Name .. out
  1318. end
  1319. end
  1320. parent = parent.Parent
  1321. end
  1322. else
  1323. return "game"
  1324. end
  1325. end
  1326.  
  1327. --- userdata-to-string: userdata
  1328. --- @param u userdata
  1329. function u2s(u)
  1330. if typeof(u) == "TweenInfo" then
  1331. -- TweenInfo
  1332. return "TweenInfo.new(" ..tostring(u.Time) .. ", Enum.EasingStyle." .. tostring(u.EasingStyle) .. ", Enum.EasingDirection." .. tostring(u.EasingDirection) .. ", " .. tostring(u.RepeatCount) .. ", " .. tostring(u.Reverses) .. ", " .. tostring(u.DelayTime) .. ")"
  1333. elseif typeof(u) == "Ray" then
  1334. -- Ray
  1335. return "Ray.new(" .. u2s(u.Origin) .. ", " .. u2s(u.Direction) .. ")"
  1336. elseif typeof(u) == "NumberSequence" then
  1337. -- NumberSequence
  1338. local ret = "NumberSequence.new("
  1339. for i, v in pairs(u.KeyPoints) do
  1340. ret = ret .. tostring(v)
  1341. if i < #u.Keypoints then
  1342. ret = ret .. ", "
  1343. end
  1344. end
  1345. return ret .. ")"
  1346. elseif typeof(u) == "DockWidgetPluginGuiInfo" then
  1347. -- DockWidgetPluginGuiInfo
  1348. return "DockWidgetPluginGuiInfo.new(Enum.InitialDockState" .. tostring(u) .. ")"
  1349. elseif typeof(u) == "ColorSequence" then
  1350. -- ColorSequence
  1351. local ret = "ColorSequence.new("
  1352. for i, v in pairs(u.KeyPoints) do
  1353. ret = ret .. "Color3.new(" .. tostring(v) .. ")"
  1354. if i < #u.Keypoints then
  1355. ret = ret .. ", "
  1356. end
  1357. end
  1358. return ret .. ")"
  1359. elseif typeof(u) == "BrickColor" then
  1360. -- BrickColor
  1361. return "BrickColor.new(" .. tostring(u.Number) .. ")"
  1362. elseif typeof(u) == "NumberRange" then
  1363. -- NumberRange
  1364. return "NumberRange.new(" .. tostring(u.Min) .. ", " .. tostring(u.Max) .. ")"
  1365. elseif typeof(u) == "Region3" then
  1366. -- Region3
  1367. local center = u.CFrame.Position
  1368. local size = u.CFrame.Size
  1369. local vector1 = center - size / 2
  1370. local vector2 = center + size / 2
  1371. return "Region3.new(" .. u2s(vector1) .. ", " .. u2s(vector2) .. ")"
  1372. elseif typeof(u) == "Faces" then
  1373. -- Faces
  1374. local faces = {}
  1375. if u.Top then
  1376. table.insert(faces, "Enum.NormalId.Top")
  1377. end
  1378. if u.Bottom then
  1379. table.insert(faces, "Enum.NormalId.Bottom")
  1380. end
  1381. if u.Left then
  1382. table.insert(faces, "Enum.NormalId.Left")
  1383. end
  1384. if u.Right then
  1385. table.insert(faces, "Enum.NormalId.Right")
  1386. end
  1387. if u.Back then
  1388. table.insert(faces, "Enum.NormalId.Back")
  1389. end
  1390. if u.Front then
  1391. table.insert(faces, "Enum.NormalId.Front")
  1392. end
  1393. return "Faces.new(" .. table.concat(faces, ", ") .. ")"
  1394. elseif typeof(u) == "EnumItem" then
  1395. return tostring(u)
  1396. elseif typeof(u) == "Enums" then
  1397. return "Enum"
  1398. elseif typeof(u) == "Enum" then
  1399. return "Enum." .. tostring(u)
  1400. elseif typeof(u) == "RBXScriptSignal" then
  1401. return "nil --[[RBXScriptSignal]]"
  1402. elseif typeof(u) == "Vector3" then
  1403. return string.format("Vector3.new(%s, %s, %s)", v2s(u.X), v2s(u.Y), v2s(u.Z))
  1404. elseif typeof(u) == "CFrame" then
  1405. return string.format("CFrame.new(%s, %s)", v2s(u.Position), v2s(u.LookVector))
  1406. elseif typeof(u) == "DockWidgetPluginGuiInfo" then
  1407. return string.format("DockWidgetPluginGuiInfo(%s, %s, %s, %s, %s, %s, %s)", "Enum.InitialDockState.Right", v2s(u.InitialEnabled), v2s(u.InitialEnabledShouldOverrideRestore), v2s(u.FloatingXSize), v2s(u.FloatingYSize), v2s(u.MinWidth), v2s(u.MinHeight))
  1408. elseif typeof(u) == "RBXScriptConnection" then
  1409. return "nil --[[RBXScriptConnection " .. tostring(u) .. "]]"
  1410. elseif typeof(u) == "RaycastResult" then
  1411. return "nil --[[RaycastResult " .. tostring(u) .. "]]"
  1412. elseif typeof(u) == "PathWaypoint" then
  1413. return string.format("PathWaypoint.new(%s, %s)", v2s(u.Position), v2s(u.Action))
  1414. else
  1415. return typeof(u) .. ".new(" .. tostring(u) .. ")"
  1416. end
  1417. end
  1418.  
  1419. --- Gets the player an instance is descended from
  1420. function getplayer(instance)
  1421. for _, v in pairs(Players:GetPlayers()) do
  1422. if v.Character and (instance:IsDescendantOf(v.Character) or instance == v.Character) then
  1423. return v
  1424. end
  1425. end
  1426. end
  1427.  
  1428. --- value-to-path (in table)
  1429. function v2p(x, t, path, prev)
  1430. if not path then
  1431. path = ""
  1432. end
  1433. if not prev then
  1434. prev = {}
  1435. end
  1436. if rawequal(x, t) then
  1437. return true, ""
  1438. end
  1439. for i, v in pairs(t) do
  1440. if rawequal(v, x) then
  1441. if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
  1442. return true, (path .. "." .. i)
  1443. else
  1444. return true, (path .. "[" .. v2s(i) .. "]")
  1445. end
  1446. end
  1447. if type(v) == "table" then
  1448. local duplicate = false
  1449. for _, y in pairs(prev) do
  1450. if rawequal(y, v) then
  1451. duplicate = true
  1452. end
  1453. end
  1454. if not duplicate then
  1455. table.insert(prev, t)
  1456. local found
  1457. found, p = v2p(x, v, path, prev)
  1458. if found then
  1459. if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
  1460. return true, "." .. i .. p
  1461. else
  1462. return true, "[" .. v2s(i) .. "]" .. p
  1463. end
  1464. end
  1465. end
  1466. end
  1467. end
  1468. return false, ""
  1469. end
  1470.  
  1471. --- format s: string, byte encrypt (for weird symbols)
  1472. function formatstr(s)
  1473. return '"' .. handlespecials(s) .. '"'
  1474. end
  1475.  
  1476. --- Adds \'s to the text as a replacement to whitespace chars and other things because string.format can't yayeet
  1477. function handlespecials(s)
  1478. local i = 0
  1479. repeat
  1480. i = i + 1
  1481. local char = s:sub(i, i)
  1482. if string.byte(char) then
  1483. if char == "\n" then
  1484. s = s:sub(0, i - 1) .. "\\n" .. s:sub(i + 1, -1)
  1485. i = i + 1
  1486. elseif char == "\t" then
  1487. s = s:sub(0, i - 1) .. "\\t" .. s:sub(i + 1, -1)
  1488. i = i + 1
  1489. elseif char == "\\" then
  1490. s = s:sub(0, i - 1) .. "\\\\" .. s:sub(i + 1, -1)
  1491. i = i + 1
  1492. elseif char == '"' then
  1493. s = s:sub(0, i - 1) .. '\\"' .. s:sub(i + 1, -1)
  1494. i = i + 1
  1495. elseif string.byte(char) > 126 or string.byte(char) < 32 then
  1496. s = s:sub(0, i - 1) .. "\\" .. string.byte(char) .. s:sub(i + 1, -1)
  1497. i = i + #tostring(string.byte(char))
  1498. end
  1499. end
  1500. until char == ""
  1501. return s
  1502. end
  1503.  
  1504. --- finds script from 'src' from getinfo, returns nil if not found
  1505. --- @param src string
  1506. function getScriptFromSrc(src)
  1507. local realPath
  1508. local runningTest
  1509. --- @type number
  1510. local s, e
  1511. local match = false
  1512. if src:sub(1, 1) == "=" then
  1513. realPath = game
  1514. s = 2
  1515. else
  1516. runningTest = src:sub(2, e and e - 1 or -1)
  1517. for _, v in pairs(getnilinstances()) do
  1518. if v.Name == runningTest then
  1519. realPath = v
  1520. break
  1521. end
  1522. end
  1523. s = #runningTest + 1
  1524. end
  1525. if realPath then
  1526. e = src:sub(s, -1):find("%.")
  1527. local i = 0
  1528. repeat
  1529. i += 1
  1530. if not e then
  1531. runningTest = src:sub(s, -1)
  1532. local test = realPath.FindFirstChild(realPath, runningTest)
  1533. if test then
  1534. realPath = test
  1535. end
  1536. match = true
  1537. else
  1538. runningTest = src:sub(s, e)
  1539. local test = realPath.FindFirstChild(realPath, runningTest)
  1540. local yeOld = e
  1541. if test then
  1542. realPath = test
  1543. s = e + 2
  1544. e = src:sub(e + 2, -1):find("%.")
  1545. e = e and e + yeOld or e
  1546. else
  1547. e = src:sub(e + 2, -1):find("%.")
  1548. e = e and e + yeOld or e
  1549. end
  1550. end
  1551. until match or i >= 50
  1552. end
  1553. return realPath
  1554. end
  1555.  
  1556. --- schedules the provided function (and calls it with any args after)
  1557. function schedule(f, ...)
  1558. table.insert(scheduled, {f, ...})
  1559. end
  1560.  
  1561. --- the big (well tbh small now) boi task scheduler himself, handles p much anything as quicc as possible
  1562. function taskscheduler()
  1563. if not toggle then
  1564. scheduled = {}
  1565. return
  1566. end
  1567. if #scheduled > 1000 then
  1568. table.remove(scheduled, #scheduled)
  1569. end
  1570. if #scheduled > 0 then
  1571. local currentf = scheduled[1]
  1572. table.remove(scheduled, 1)
  1573. if type(currentf) == "table" and type(currentf[1]) == "function" then
  1574. pcall(unpack(currentf))
  1575. end
  1576. end
  1577. end
  1578.  
  1579. --- Handles remote logs
  1580. function remoteHandler(hookfunction, methodName, remote, args, func, calling)
  1581. if remote:IsA("RemoteEvent") or remote:IsA("RemoteFunction") then
  1582. if funcEnabled and not calling then
  1583. _, calling = pcall(getScriptFromSrc, debug.getinfo(func).source)
  1584. end
  1585. coroutine.wrap(function()
  1586. if remoteSignals[remote] then
  1587. remoteSignals[remote]:Fire(args)
  1588. end
  1589. end)()
  1590. if autoblock then
  1591. if excluding[remote] then
  1592. return
  1593. end
  1594. if not history[remote] then
  1595. history[remote] = {badOccurances = 0, lastCall = tick()}
  1596. end
  1597. if tick() - history[remote].lastCall < 1 then
  1598. history[remote].badOccurances += 1
  1599. return
  1600. else
  1601. history[remote].badOccurances = 0
  1602. end
  1603. if history[remote].badOccurances > 3 then
  1604. excluding[remote] = true
  1605. return
  1606. end
  1607. history[remote].lastCall = tick()
  1608. end
  1609. local functionInfoStr
  1610. local src
  1611. if func and islclosure(func) then
  1612. local functionInfo = {}
  1613. pcall(function() functionInfo.info = debug.getinfo(func) end)
  1614. pcall(function() functionInfo.constants = debug.getconstants(func) end)
  1615. pcall(function() functionInfoStr = v2v{functionInfo = functionInfo} end)
  1616. pcall(function() if type(calling) == "userdata" then src = calling end end)
  1617. end
  1618. if methodName:lower() == "fireserver" then
  1619. newRemote("event", remote.Name, genScript(remote, table.unpack(args)), remote, functionInfoStr, (blocklist[remote] or blocklist[remote.Name]), src)
  1620. elseif methodName:lower() == "invokeserver" then
  1621. newRemote("function", remote.Name, genScript(remote, table.unpack(args)), remote, functionInfoStr, (blocklist[remote] or blocklist[remote.Name]), src)
  1622. end
  1623. end
  1624. end
  1625.  
  1626. --- Used for hookfunction
  1627. function hookRemote(remoteType, remote, ...)
  1628. local args = {...}
  1629. if remoteHooks[remote] then
  1630. args = remoteHooks[remote](args)
  1631. end
  1632. if typeof(remote) == "Instance" and not (blacklist[remote] or blacklist[remote.Name]) then
  1633. local func
  1634. local calling
  1635. if funcEnabled then
  1636. func = debug.getinfo(4).func
  1637. calling = useGetCallingScript and getcallingscript() or nil
  1638. end
  1639. schedule(remoteHandler, true, remoteType == "RemoteEvent" and "fireserver" or "invokeserver", remote, args, func, calling)
  1640. if (blocklist[remote] or blocklist[remote.Name]) then
  1641. return
  1642. end
  1643. end
  1644. if remoteType == "RemoteEvent" then
  1645. if remoteHooks[remote] then
  1646. return originalEvent(remote, unpack(args))
  1647. end
  1648. return originalEvent(remote, ...)
  1649. else
  1650. if remoteHooks[remote] then
  1651. return originalFunction(remote, unpack(args))
  1652. end
  1653. return originalFunction(remote, ...)
  1654. end
  1655. end
  1656.  
  1657. local newnamecall = newcclosure(function(...)
  1658. local args = {...}
  1659. local methodName = getnamecallmethod()
  1660. local remote = args[1]
  1661. if (methodName:lower() == "invokeserver" or methodName:lower() == "fireserver") and not (blacklist[remote] or blacklist[remote.Name]) then
  1662. if remoteHooks[remote] then
  1663. args = remoteHooks[remote]({args, unpack(args, 2)})
  1664. end
  1665. local func
  1666. local calling
  1667. if funcEnabled then
  1668. func = debug.getinfo(3).func
  1669. calling = useGetCallingScript and getcallingscript() or nil
  1670. end
  1671. coroutine.wrap(function()
  1672. schedule(remoteHandler, false, methodName, remote, {unpack(args, 2)}, func, calling)
  1673. end)()
  1674. end
  1675. if typeof(remote) == "Instance" and (methodName:lower() == "invokeserver" or methodName:lower() == "fireserver") and (blocklist[remote] or blocklist[remote.Name]) then
  1676. return nil
  1677. elseif (methodName:lower() == "invokeserver" or methodName:lower() == "fireserver") and remoteHooks[remote] then
  1678. return original(unpack(args))
  1679. else
  1680. return original(...)
  1681. end
  1682. end)
  1683.  
  1684. local newFireServer = newcclosure(function(...) return hookRemote("RemoteEvent", ...) end)
  1685.  
  1686. local newInvokeServer = newcclosure(function(...) return hookRemote("RemoteFunction", ...) end)
  1687.  
  1688. --- Toggles on and off the remote spy
  1689. function toggleSpy()
  1690. if not toggle then
  1691. setreadonly(gm, false)
  1692. if not original then
  1693. original = gm.__namecall
  1694. if not original then
  1695. warn("SimpleSpy: namecall method not found!\n")
  1696. onToggleButtonClick()
  1697. return
  1698. end
  1699. end
  1700. gm.__namecall = newnamecall
  1701. originalEvent = hookfunction(remoteEvent.FireServer, newFireServer)
  1702. originalFunction = hookfunction(remoteFunction.InvokeServer, newInvokeServer)
  1703. else
  1704. setreadonly(gm, false)
  1705. gm.__namecall = original
  1706. hookfunction(remoteEvent.FireServer, originalEvent)
  1707. hookfunction(remoteFunction.InvokeServer, originalFunction)
  1708. end
  1709. end
  1710.  
  1711. --- Toggles between the two remotespy methods (hookfunction currently = disabled)
  1712. function toggleSpyMethod()
  1713. toggleSpy()
  1714. toggle = not toggle
  1715. end
  1716.  
  1717. --- Shuts down the remote spy
  1718. function shutdown()
  1719. if schedulerconnect then
  1720. schedulerconnect:Disconnect()
  1721. end
  1722. for _, connection in pairs(connections) do
  1723. coroutine.wrap(function()
  1724. connection:Disconnect()
  1725. end)()
  1726. end
  1727. setreadonly(gm, false)
  1728. SimpleSpy2:Destroy()
  1729. hookfunction(remoteEvent.FireServer, originalEvent)
  1730. hookfunction(remoteFunction.InvokeServer, originalFunction)
  1731. gm.__namecall = original
  1732. _G.SimpleSpyExecuted = false
  1733. end
  1734.  
  1735. -- main
  1736. if not _G.SimpleSpyExecuted then
  1737. local succeeded, err = pcall(function()
  1738. _G.SimpleSpyShutdown = shutdown
  1739. ContentProvider:PreloadAsync({"rbxassetid://6065821980", "rbxassetid://6065774948", "rbxassetid://6065821086", "rbxassetid://6065821596", ImageLabel, ImageLabel_2, ImageLabel_3})
  1740. onToggleButtonClick()
  1741. RemoteTemplate.Parent = nil
  1742. FunctionTemplate.Parent = nil
  1743. codebox = Highlight.new(CodeBox)
  1744. codebox:setRaw("")
  1745. getgenv().SimpleSpy = SimpleSpy
  1746. TextLabel:GetPropertyChangedSignal("Text"):Connect(scaleToolTip)
  1747. TopBar.InputBegan:Connect(onBarInput)
  1748. MinimizeButton.MouseButton1Click:Connect(toggleMinimize)
  1749. MaximizeButton.MouseButton1Click:Connect(toggleSideTray)
  1750. Simple.MouseButton1Click:Connect(onToggleButtonClick)
  1751. CloseButton.MouseEnter:Connect(onXButtonHover)
  1752. CloseButton.MouseLeave:Connect(onXButtonUnhover)
  1753. Simple.MouseEnter:Connect(onToggleButtonHover)
  1754. Simple.MouseLeave:Connect(onToggleButtonUnhover)
  1755. CloseButton.MouseButton1Click:Connect(shutdown)
  1756. table.insert(connections, UserInputService.InputBegan:Connect(backgroundUserInput))
  1757. table.insert(connections, Mouse.Move:Connect(mouseMoved))
  1758. connectResize()
  1759. SimpleSpy2.Enabled = true
  1760. coroutine.wrap(function()
  1761. wait(1)
  1762. onToggleButtonUnhover()
  1763. end)()
  1764. schedulerconnect = RunService.Heartbeat:Connect(taskscheduler)
  1765. if syn and syn.protect_gui then pcall(syn.protect_gui, SimpleSpy2) end
  1766. SimpleSpy2.Parent = gethui and gethui() or CoreGui
  1767. end)
  1768. if succeeded then
  1769. _G.SimpleSpyExecuted = true
  1770. else
  1771. warn("A fatal error has occured, SimpleSpy was unable to launch properly.\nPlease DM this error message to @exx#9394:\n\n" .. tostring(err))
  1772. SimpleSpy2:Destroy()
  1773. hookfunction(remoteEvent.FireServer, originalEvent)
  1774. hookfunction(remoteFunction.InvokeServer, originalFunction)
  1775. gm.__namecall = original
  1776. return
  1777. end
  1778. else
  1779. SimpleSpy2:Destroy()
  1780. return
  1781. end
  1782.  
  1783. ----- ADD ONS ----- (easily add or remove additonal functionality to the RemoteSpy!)
  1784. --[[
  1785. Some helpful things:
  1786. - add your function in here, and create buttons for them through the 'newButton' function
  1787. - the first argument provided is the TextButton the player clicks to run the function
  1788. - generated scripts are generated when the namecall is initially fired and saved in remoteFrame objects
  1789. - blacklisted remotes will be ignored directly in namecall (less lag)
  1790. - the properties of a 'remoteFrame' object:
  1791. {
  1792. Name: (string) The name of the Remote
  1793. GenScript: (string) The generated script that appears in the codebox (generated when namecall fired)
  1794. Source: (Instance (LocalScript)) The script that fired/invoked the remote
  1795. Remote: (Instance (RemoteEvent) | Instance (RemoteFunction)) The remote that was fired/invoked
  1796. Log: (Instance (TextButton)) The button being used for the remote (same as 'selected.Log')
  1797. }
  1798. - globals list: (contact @exx#9394 for more information or if you have suggestions for more to be added)
  1799. - closed: (boolean) whether or not the GUI is currently minimized
  1800. - logs: (table[remoteFrame]) full of remoteFrame objects (properties listed above)
  1801. - selected: (remoteFrame) the currently selected remoteFrame (properties listed above)
  1802. - blacklist: (string[] | Instance[] (RemoteEvent) | Instance[] (RemoteFunction)) an array of blacklisted names and remotes
  1803. - codebox: (Instance (TextBox)) the textbox that holds all the code- cleared often
  1804. ]]
  1805. -- Copies the contents of the codebox
  1806. newButton(
  1807. "Copy Code",
  1808. function() return "Click to copy code" end,
  1809. function()
  1810. setclipboard(codebox:getString())
  1811. TextLabel.Text = "Copied successfully!"
  1812. end
  1813. )
  1814.  
  1815. --- Copies the source script (that fired the remote)
  1816. newButton(
  1817. "Copy Remote",
  1818. function() return "Click to copy the path of the remote" end,
  1819. function()
  1820. if selected then
  1821. setclipboard(v2s(selected.Remote))
  1822. TextLabel.Text = "Copied!"
  1823. end
  1824. end
  1825. )
  1826.  
  1827. -- Executes the contents of the codebox through loadstring
  1828. newButton(
  1829. "Run Code",
  1830. function() return "Click to execute code" end,
  1831. function()
  1832. local orText = "Click to execute code"
  1833. TextLabel.Text = "Executing..."
  1834. local succeeded = pcall(function() return loadstring(codebox:getString())() end)
  1835. if succeeded then
  1836. TextLabel.Text = "Executed successfully!"
  1837. else
  1838. TextLabel.Text = "Execution error!"
  1839. end
  1840. end
  1841. )
  1842.  
  1843. --- Gets the calling script (not super reliable but w/e)
  1844. newButton(
  1845. "Get Script",
  1846. function() return "Click to copy calling script to clipboard\nWARNING: Not super reliable, nil == could not find" end,
  1847. function()
  1848. if selected then
  1849. setclipboard(SimpleSpy:ValueToString(selected.Source))
  1850. TextLabel.Text = "Done!"
  1851. end
  1852. end
  1853. )
  1854.  
  1855. --- Decompiles the script that fired the remote and puts it in the code box
  1856. newButton(
  1857. "Function Info",
  1858. function() return "Click to view calling function information" end,
  1859. function()
  1860. if selected then
  1861. if selected.Function then
  1862. codebox:setRaw("-- Calling function info\n-- Generated by the SimpleSpy serializer\n\n" .. tostring(selected.Function))
  1863. end
  1864. TextLabel.Text = "Done! Function info generated by the SimpleSpy Serializer."
  1865. end
  1866. end
  1867. )
  1868.  
  1869. --- Clears the Remote logs
  1870. newButton(
  1871. "Clr Logs",
  1872. function() return "Click to clear logs" end,
  1873. function()
  1874. TextLabel.Text = "Clearing..."
  1875. logs = {}
  1876. for _, v in pairs(LogList:GetChildren()) do
  1877. if not v:IsA("UIListLayout") then
  1878. v:Destroy()
  1879. end
  1880. end
  1881. codebox:setRaw("")
  1882. selected = nil
  1883. TextLabel.Text = "Logs cleared!"
  1884. end
  1885. )
  1886.  
  1887. --- Excludes the selected.Log Remote from the RemoteSpy
  1888. newButton(
  1889. "Exclude (i)",
  1890. function() return "Click to exclude this Remote" end,
  1891. function()
  1892. if selected then
  1893. blacklist[selected.Remote] = true
  1894. TextLabel.Text = "Excluded!"
  1895. end
  1896. end
  1897. )
  1898.  
  1899. --- Excludes all Remotes that share the same name as the selected.Log remote from the RemoteSpy
  1900. newButton(
  1901. "Exclude (n)",
  1902. function() return "Click to exclude all remotes with this name" end,
  1903. function()
  1904. if selected then
  1905. blacklist[selected.Name] = true
  1906. TextLabel.Text = "Excluded!"
  1907. end
  1908. end
  1909. )
  1910.  
  1911. --- clears blacklist
  1912. newButton(
  1913. "Clr Blacklist",
  1914. function() return "Click to clear the blacklist" end,
  1915. function()
  1916. blacklist = {}
  1917. TextLabel.Text = "Blacklist cleared!"
  1918. end
  1919. )
  1920.  
  1921. --- Prevents the selected.Log Remote from firing the server (still logged)
  1922. newButton(
  1923. "Block (i)",
  1924. function() return "Click to stop this remote from firing" end,
  1925. function()
  1926. if selected then
  1927. blocklist[selected.Remote] = true
  1928. TextLabel.Text = "Excluded!"
  1929. end
  1930. end
  1931. )
  1932.  
  1933. --- Prevents all remotes from firing that share the same name as the selected.Log remote from the RemoteSpy (still logged)
  1934. newButton(
  1935. "Block (n)",
  1936. function() return "Click to stop remotes with this name from firing" end,
  1937. function()
  1938. if selected then
  1939. blocklist[selected.Name] = true
  1940. TextLabel.Text = "Excluded!"
  1941. end
  1942. end
  1943. )
  1944.  
  1945. --- clears blacklist
  1946. newButton(
  1947. "Clr Blocklist",
  1948. function() return "Click to stop blocking remotes" end,
  1949. function()
  1950. blocklist = {}
  1951. TextLabel.Text = "Blocklist cleared!"
  1952. end
  1953. )
  1954.  
  1955. --- Attempts to decompile the source script
  1956. newButton(
  1957. "Decompile",
  1958. function() return "Attempts to decompile source script\nWARNING: Not super reliable, nil == could not find" end,
  1959. function()
  1960. if selected then
  1961. if selected.Source then
  1962. codebox:setRaw(decompile(selected.Source))
  1963. TextLabel.Text = "Done!"
  1964. else
  1965. TextLabel.Text = "Source not found!"
  1966. end
  1967. end
  1968. end
  1969. )
  1970.  
  1971. newButton(
  1972. "Disable Info",
  1973. function() return string.format("[%s] Toggle function info (because it can cause lag in some games)", funcEnabled and "ENABLED" or "DISABLED") end,
  1974. function()
  1975. funcEnabled = not funcEnabled
  1976. TextLabel.Text = string.format("[%s] Toggle function info (because it can cause lag in some games)", funcEnabled and "ENABLED" or "DISABLED")
  1977. end
  1978. )
  1979.  
  1980. newButton(
  1981. "Autoblock",
  1982. function() return string.format("[%s] [BETA] Intelligently detects and excludes spammy remote calls from logs", autoblock and "ENABLED" or "DISABLED") end,
  1983. function()
  1984. autoblock = not autoblock
  1985. TextLabel.Text = string.format("[%s] [BETA] Intelligently detects and excludes spammy remote calls from logs", autoblock and "ENABLED" or "DISABLED")
  1986. history = {}
  1987. excluding = {}
  1988. end
  1989. )
  1990.  
  1991. newButton(
  1992. "CallingScript",
  1993. function() return string.format("[%s] [UNSAFE] Uses 'getcallingscript' to get calling script for Decompile and GetScript. Much more reliable, but opens up SimpleSpy to detection and/or instability.", useGetCallingScript and "ENABLED" or "DISABLED") end,
  1994. function()
  1995. useGetCallingScript = not useGetCallingScript
  1996. TextLabel.Text = string.format("[%s] [UNSAFE] Uses 'getcallingscript' to get calling script for Decompile and GetScript. Much more reliable, but opens up SimpleSpy to detection and/or instability.", useGetCallingScript and "ENABLED" or "DISABLED")
  1997. end
  1998. )
Add Comment
Please, Sign In to add comment