Currently it doesn’t run scripts inside of the simulated assemblies. I want to add the option to select which scripts to run during simulation and actually run them without the user needing to modify the scripts beforehand, but i dont know how to. i want to run it in such a way that i can run, stop and restart when the user start/stops the simulation. how can i achieve this?
Since plugins have access to script.source, I’d imagine you could automatically replace any "script.Parent"s with game.Workspace.blahblah.doodad, and then use the (incredibly insecure for normal use!!!)loadstring() function. Dunno how exactly it would have to be put together, but I hope this helps nonetheless.
Nevermind what I said before lol because you definitely can’t upload plugins that use loadtring() or otherwise execute scripts for any reason, BUT it seems like you can use it personally as a local plugin. if you’re unsure probably CTRL+F the Terms Of Service for plugin stuff.
im looking into this atm, the only issue is that if a script is run, and has connections inside of it, even if you were to delete the script, those connections still persist. im looking for a way to completely stop a script from running when needed.
thats fine thanks for the little help. currently i decided to take the LONG route and created a function that reads through the source of a script, stores every connection into a non local variable, insert them into a table, and returns it at the end:
Original Test Code
-- Test script for connection detection
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
RunService.Heartbeat:Connect(function()
print("Heartbeat")
end)
local mouseConnection = UserInputService.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
print("Mouse clicked")
end
end)
local keyboardConnection = UserInputService.InputEnded:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Space then
print("Space released")
elseif input.KeyCode == Enum.KeyCode.W then
print("W released")
end
end)
local function playerAdded(player)
print(player.Name .. " joined the game")
player.CharacterAdded:Connect(function(character)
print(player.Name .. "'s character spawned")
end)
end
Players.PlayerAdded:Connect(playerAdded)
if true then
local conditionalConnection = RunService.RenderStepped:Connect(function()
print("RenderStepped")
end)
end
Modified Code
local SCRIPTCONNECTIONS = {}
-- Test script for connection detection
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
connection_7 = RunService.Heartbeat:Connect(function()
print("Heartbeat")
end)
mouseConnection = UserInputService.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1 then
print("Mouse clicked")
end
end)
keyboardConnection = UserInputService.InputEnded:Connect(function(input)
if input.KeyCode == Enum.KeyCode.Space then
print("Space released")
elseif input.KeyCode == Enum.KeyCode.W then
print("W released")
end
end)
local function playerAdded(player)
print(player.Name .. " joined the game")
connection_28 = player.CharacterAdded:Connect(function(character)
print(player.Name .. "'s character spawned")
end)
end
connection_33 = Players.PlayerAdded:Connect(playerAdded)
if true then
conditionalConnection = RunService.RenderStepped:Connect(function()
print("RenderStepped")
end)
end
-- Collect all connections
table.insert(SCRIPTCONNECTIONS, connection_7)
table.insert(SCRIPTCONNECTIONS, mouseConnection)
table.insert(SCRIPTCONNECTIONS, keyboardConnection)
table.insert(SCRIPTCONNECTIONS, connection_28)
table.insert(SCRIPTCONNECTIONS, connection_33)
table.insert(SCRIPTCONNECTIONS, conditionalConnection)
return SCRIPTCONNECTIONS
with this i should theoretically be able to disconnect these remotely when needed. Hopefully…
the method works! i created a test plugin to show it working. It converts any script into a module that returns its connections, so that you can disconnect them afterwards.
code:
local env = script.Parent
local gui = env.Frame
local startButton = gui.Start
local stopButton = gui.Stop
local toolbar = plugin:CreateToolbar("Script Runner")
local openButton = toolbar:CreateButton("toggleOpen", "", "", "Open")
local currentScript = nil
local connections = {}
-- Simple connection processor
local function processScriptConnections(scriptSource)
-- Create a new script with the SCRIPTCONNECTIONS table at the top
local newSource = "local SCRIPTCONNECTIONS = {}\n\n"
-- Split the script into lines
local lines = {}
local connectionVars = {}
for line in scriptSource:gmatch("([^\n]*)\n?") do
table.insert(lines, line)
end
-- Process each line
for i, line in ipairs(lines) do
-- Look for connections
if line:find(":[Cc]onnect%(") then
-- Is this already a variable assignment?
if line:match("^%s*local%s+([%w_]+)%s*=") then
-- It's a local variable, change to non-local
local varName = line:match("^%s*local%s+([%w_]+)%s*=")
newSource = newSource .. line:gsub("^%s*local%s+", "") .. "\n"
table.insert(connectionVars, varName)
elseif line:match("^%s*([%w_]+)%s*=") then
-- Already a non-local variable, keep as is
local varName = line:match("^%s*([%w_]+)%s*=")
newSource = newSource .. line .. "\n"
table.insert(connectionVars, varName)
else
-- Inline connection, create a non-local variable
local varName = "connection_" .. i
local indent = line:match("^(%s*)")
newSource = newSource .. indent .. varName .. " = " .. line:gsub("^%s*", "") .. "\n"
table.insert(connectionVars, varName)
end
else
-- Not a connection, keep the line as is
newSource = newSource .. line .. "\n"
end
end
-- Add code to collect connections at the end
newSource = newSource .. "\n-- Collect all connections\n"
for _, varName in ipairs(connectionVars) do
newSource = newSource .. "table.insert(SCRIPTCONNECTIONS, " .. varName .. ")\n"
end
-- Add return statement
newSource = newSource .. "\nreturn SCRIPTCONNECTIONS"
-- Create the module script
local moduleScript = Instance.new("ModuleScript")
moduleScript.Name = "ConnectionsModule"
moduleScript.Source = newSource
return moduleScript
end
local dockWidgetInfo = DockWidgetPluginGuiInfo.new(
Enum.InitialDockState.Float,
false,
false,
100,
100,
100,
100
)
local dockWidget = plugin:CreateDockWidgetPluginGui("Script Loader", dockWidgetInfo)
gui.Parent = dockWidget
openButton.Click:Connect(function()
dockWidget.Enabled = not dockWidget.Enabled
end)
startButton.Activated:Connect(function()
local originalScript = game.Selection:Get()[1]
if not originalScript:IsA("Script") and not originalScript:IsA("LocalScript") then return end
local processedScript = processScriptConnections(originalScript.Source)
processedScript.Name = originalScript.Name .. "_PLUGIN"
processedScript.Parent = originalScript.Parent
currentScript = processedScript
connections = require(processedScript)
end)
stopButton.Activated:Connect(function()
for _, connection in connections do
connection:Disconnect()
connection = nil
end
currentScript:Destroy()
end)
the proccessScriptConnections is what detects the connections in the source and stores them into a table.
Example:
Caveats:
while it can run scripts with a while true loop, it is unable to stop it, so avoid doing that.