Textbox as in-game code runner

So is this just a virtial script interface?

Both of these options are a billion trillion times simpler and more reliable than whatever you were doing above this.

Normally print() will output a message to the log, which you can get with LogService.
I suggested replacing print with something that outputs to the GUI directly instead of the log.
e.g.

function print(...)
	local messages = {...}
	-- convert each argument to string
	for i, message in ipairs(messages) do
		messages[i] = tostring(message)
	end
	-- show the result in a textlabel
	local TextLabel = game.ReplicatedStorage.Output:Clone()
	TextLabel.Text = table.concat(messages, "\t")
	TextLabel.Parent = Player.PlayerGui.NC.Output.ScrollingFrame
end

The first option was to replace the environment of the function.

local env = {
	print = print, -- the print function from above
	Player = Player, -- the player that ran this code
	game = game, -- you'll have to add a LOT of stuff here
}

local func = loadstring(YOUR_CODE_HERE)
setfenv(func, env)
func()

The second option was to add code that runs before your user’s code.
This is a lot less reliable, though. In fact, it’s very poor form, but still better than reading the console.

local preamble = [[
local Player = ]] .. Player:GetFullName() .. [[

function print(...)
	local messages = {...}
	-- convert each argument to string
	for i, message in ipairs(messages) do
		messages[i] = tostring(message)
	end
	-- show the result in a textlabel
	local TextLabel = game.ReplicatedStorage.Output:Clone()
	TextLabel.Text = table.concat(messages, "\t")
	TextLabel.Parent = Player.PlayerGui.NC.Output.ScrollingFrame
end

]]

local func = loadstring(preamble .. YOUR_CODE_HERE)
func()

Well is like roblox studio command bar or script runner but in-game.

How to use the first option tho?

I know the point of option 2, but like you said it’s less reliable as option 1. So how to use option 1?

But second option I try and it says attempt to index nil with robloxjw02 ← my username

That’s what I meant by ‘less reliable’. It’s generating code that tries and fails to get game.Players.

How to use the first option tho?

You just use setfenv(func, environment) to change the environment of a function to another table.

has an example of this.

I’m not sure how you couldn’t get the first one to work if you could make the second one run and show an error.

local RemoteEvent = game.ReplicatedStorage.Test

--local Modules = game.ReplicatedStorage.Loadstring

--local LogService = game:GetService("LogService")

local Players = game:GetService("Players")

RemoteEvent.OnServerEvent:Connect(function(Player, Text)

local preamble = [[

local preamble = [[

local Player = ]] .. Player:GetFullName() .. [[

function print(...)

local messages = {...}

-- convert each argument to string

for i, message in ipairs(messages) do

messages[i] = tostring(message)

end

-- show the result in a textlabel

local TextLabel = game.ReplicatedStorage.Output:Clone()

TextLabel.Text = table.concat(messages, "\t")

TextLabel.Parent = Player.PlayerGui.NC.Output.ScrollingFrame

end

]]

local func = loadstring(preamble..Text)

func()

end)

This is my code now using your second option.

If i use the first option, where should i put the function print(…), inside ServerEvent or outside?

Ah no, your first option works. But i don’t see anything on the command bar is it because of setenv?

It works, it gives the textlabel, but it doesn’t show anything on Roblox Studio Output, is it because of SetEnv?

It doesn’t show anything on the output because it wasn’t programmed to write anything to studio output, only to the GUI.

If you want that, just make it print as well.

local realprint = print
local function print(...)
	realprint(...)
	local messages = {...}
	-- convert each argument to string
	for i, message in ipairs(messages) do
		messages[i] = tostring(message)
	end
	-- show the result in a textlabel
	local TextLabel = game.ReplicatedStorage.Output:Clone()
	TextLabel.Text = table.concat(messages, "\t")
	TextLabel.Parent = Player.PlayerGui.NC.Output.ScrollingFrame
end

Ahh, but it’s only for print right? If I want to make let’s say Instance.new I need to make new function? Well this is only for curiousity.

If you try to do Instance.new() and it errors, then you didn’t include Instance in the environment.
Just add Instance = Instance to the env table.

Now that I think about it, you might get away with using the current environment when setting up the function.
Something like

setfenv(func, getfenv(1))

In this case, make sure that the custom print function is not a local (is function print(...) not local function print(...) so that it ends up in the env, not as a local)

Ah I get it , but in this case, for loadstring, how to get Player tho in the text editor, because I want to check it for yeah instance parent

I suppose to get Player you need to make Players.yourusername right? Because I try to use Player.PlayerGui it index nil for PlayerGui, if I try Player.Name it will return nil too ← this is without making local Player = Players.yourusername inside the textbox.

Contextually it would run based on where the script is so if you wanted the player you’d have to either locate their instance directly based on client or server, or create a locating function specifically for players or custom instances you want to find possibly. You could format it all in a module and let the module save and edit the scripts

If you mean that it shows (in Studio’s console) an error similar to:
Attempt to index nil with PlayerGui
then Player is nil, for some reason. The error means that the code is trying to do nil.PlayerGui, which is not possible, there’s nothing inside a nil.

If you are using this

local env = {
	print = print, -- the print function from above
	Player = Player, -- the player that ran this code
	game = game, -- you'll have to add a LOT of stuff here
}
-- ...
setfenv(func, env)

then either your Player was nil in the place where you’re loadstring()ing the code, or something’s really wrong.

But if you’re using this:

setfenv(func, getfenv(1))

then you’ll need to make Player a global variable (environment variable), not a local value.
Look for local Player = somewhere in your code and replace it with just Player =


is there a way to output something like this when we made instance with script on studio it has output like this, can we do the same to the gui? Or maybe it’s kinda hard to explain?

But thank you, I will mark yours as solution, I will make new topic, now for HighlightSyntax, maybe you can help again there, thanks.

1 Like