You can use a for loop to accomplish it. I would reccomend against using loadstrings for this, as your game can be vulnerable to lua injections.
You use a recursive function.
local splitString = {“split”,”string”}
local function getDescendant(parent, descendant,pos)
if not parent then return end
I = i or 1
return getDescendant(parent:FindFirstChild(“descendant”),splitString[i], i + 1)
end
getDescendant(game.Workspace, splitString)
No it wouldn’t, loadstring is server-sided and you can sandbox it, it would not make the game vulnerable in any circumstance if it is sandboxed correctly.
@grilme99 is looking for an efficient way, loadstring will be the most efficient solution currently and safest as it’s easiest to sandbox (stop bad code from running).
Yeah I get that you can sandbox loadstring, but that fact that this is going to be used in a massive variety of games, I don’t want to have everyone need to enable a feature that is disabled for security reasons.
Either way you’d want to sandbox user inputted code (assuming that this is for user inputted code), so any other method would just be much harder to implement and sandbox. If you’re looking for the most efficient solution then loadstring will be your best option.
If you don’t plan to use loadstring then what other methods are you looking for?
I’ll say it again. I plan on lots of games using this. I don’t want them all having to enable extra features for such a small thing.
I am going to use @tlr22’s suggestion, most likely.
I won’t lecture you on how it should be made, but with long lines of code that recursive function will end up not being efficient at all.
In all honesty, clever’s method is more efficient if you are talking about efficiency. This is a lot easier to use, and saves a lot of stress. LoadStrings as Clever mentioned, can’t be loaded client-side.
I don’t really understand how it is more efficient and secure than just using @tlr22’s method. Can you please explain? Obviously it can’t be used client side, but it puts games at more of a risk of backdoors executing code.
I mean your code can already execute code so it wouldn’t matter. I don’t want to keep repeating myself but like I said if you sandbox it then it’s perfectly secure, I can even provide an entire sandbox that from my knowledge can’t be “escaped”.
Also efficiency wise; loadstring()
is meant to execute lua code, making a recursive function that is meant to read code and “execute it” will eventually become inefficient when you attempt to execute massive lines of code.
I don’t think there is anything else to clarify on the topic as you’ve already chosen a solution and I’ve already outlined all the “pros & cons” of using loadstring()
vs a recursive function.
I’m guessing you’re referring to my project the Marketplace which I made posts about before. We don’t simply “execute code”. We turn code into obfuscated bytecode which is then ran by a custom interpreter. We never use the built in loadstring.
Using a recursive method is far more efficient than using bandwidth (which I am cheated for) to send that bytecode to the game.
The recursive also doesn’t read and handle code, it just takes in the path of an object (game.Workspace.Part, for example).
Try using recursive method for like 200 lines of code, the server will instantly crash, with loadstrings however, this isn’t an issue.
Why would I use recursive for 200 lines of code?
I’m curious as to why you’ve decided that the hierarchical name of the instance must be passed rather than a reference to the instance itself (i.e. workspace.Baseplate
instead of "workspace.Baseplate"
).
There are some issues with using hierarchical names to index instances in the data model:
-
These names are not necessarily unique; instance references are always unique. Suppose for example that there exist two instances in
Workspace
that are both namedBaseplate
: the hierarchical names of these instances will be identical. Since the same name can map to multiple instances, it’s a lot more difficult than it should be to determine which particular instance we’re actually interested in. -
Hierarchical names may change; instance references may never change. Changing the properties
.Parent
or.Name
on an instance will alter its hierarchical name. What this means practically is that the full hierarchical name has to be passed and resolved every time you want to reference an instance, which is a lot more time spent processing than is necessary. -
In terms of data size, hierarchical names are big; instance references are tiny. Each additional character in a string occupies 1 byte, while an instance reference is a single 4-byte integer. This usually isn’t something to be concerned about since strings are interned, but one place where it is important is when sending them over remotes. In this case, each string will occupy
5 + string.len(str)
bytes (assuming it isn’t already cached) in the next network message, while an instance reference will only require 5 bytes.
My use case is a little confusing.
Essentially, though - I’m creating a website that provides tools for protecting the source of scripts.
I found that one of the best ways to do this is for code to never be sent to the game in the first place. Let me explain - your products code runs in a sandboxed Lua environment on one of our servers. Then, when the script needs to interact with the game, it either sends a predefined instruction or obfuscated bytecode which is then ran with an interpreter made for it.
The reason I don’t just use a reference to the instance itself is because I can’t. Code is running on our server, not the game. So when you need to get a part you have to tell the game to return data about it.
In that case, I would recommend JSON as a way to pass the hierarchy instead of the signature as a string. Both will still work though if you prefer that route. Also, you will need some way to verify if there is more than one object with the same name, or just avoid the situation entirely. That’s a pretty neat idea, to keep your code running externally, though I wonder how much latency would affect it’s usage.
What’s the point in this? Exploiters can just fetch the bytecode, as for code to run on the client, they’re always given bytecode (even if you run it with an interpreter). They can still fetch source code.
Sure this could prevent client sided place stealing as the client code will not be there but as soon as it runs in the actual game the exploiter can easily construct source code from all the ran bytecode.
I recommend reading up on this.
I’m not sure if we’re both talking about the same thing.
My assumption is that what they meant is that the logic is being offloaded to an http server? Please correct me if I’m wrong. What it seems to me is that the intention is not to prevent client side decompiling etc, but to be able to sell scripts to developers without them being leaked. I might be confusing this with a similar thread though, since I remember another thread talking about this.
Exploiters can’t simply “fetch the bytecode”. The bytecode is heavily obfuscated so that it will only work when being ran by the interpreter.
Because of this, trying to use a decompiler to view the interpreted script will error because it’s not normal Roblox bytecode.
To accomplish this, I am buying part of the Ironbrew VM. Ironbrew is one of the best Lua obfuscators and has never been crack. It has a $420 deobfuscation bounty.
When I first started the project, the main goal was to replace closed source modules. As someone would depended on them for my income on the platform, they were really important for me. However, I have also looked into other potential usages and, yes, game security is one. This project is a website that anyone can use, so the usages will vary greatly.
As for latency, it’s only an issue when you don’t design with it in mind. For example, to remove the latency issue all together you could simply not do logic on our server and do it on the game instead. Here’s an example,
local functions = marketplace.functions()
functions.game.playerAdded(function(player)
functions.executeClientCode(player,
“print(‘Hello world!’)”
)
end)
You could put all of your client code there when they join and have it execute on Roblox normally without any latency.
It is both.