Jump to content

loadstring and wrappers


Bonsai

Recommended Posts

That snippet of code is irrelevant. You talk about an issue on setfenv call but you show nothing about it.

As I said, I'm doing it just like u did in your example, but with some script not only one command.

  
local env = {} 
--env.all functions... 
function loadScript(file, dim) 
  
dimension = dim 
local file = fileOpen(file) 
local content = fileRead(file, fileGetSize(file)) 
local loaded = loadstring(content) 
setfenv(loaded, env) 
pcall(loaded) 
  
end 
_addEventHandler("onLoadScript", root, loadScript) 

Link to comment
  • Replies 57
  • Created
  • Last Reply

Top Posters In This Topic

Can you send me all of the source code (either here or via PM, if you don't want to share it with everybody) so I can see what you're doing?
@Bonsai, default environment is always empty and has no default functions. Try changing your env table to "local env = { outputChatBox = outputChatBox }" and run a script which has ONLY outputChatBox in it. It will work.

Yeah, I know.

I added all the function that are in that script like env.function.

But it didn't work.

I'll add this again and show it to u guys.

Link to comment

Alright, I tested loading a few different script.

Turned out they all work, except the ones who contain eventHandlers.

CommandHandlers or timers work fine, but eventHandlers are screwing it up.

Works:

env = {}

env.setTimer = setTimer

Doesn't:

env = {}

env.addEventHandler = addEventHandler

Now, whats the problem here? EventHandler work fine when I'm not using setfenv.

And of course I'm replacing the "onResourceStart" event.

Bonsai

Link to comment

I think you still didn't get what an environment is or how it works. Every function, every variable (except locals, which are stored somewhere else) is stored in the environment table. The default environment is _G. Whenever you call a function, Lua attempts to find it in the environment table - it is the same as _G["function_name"] ( ... ) or even _G.function_name ( ... ) (which is syntatic sugar). Locals are not stored in the environment, that's why using local variables is faster than using global ones - you avoid a lookup in the environment table, which may be very slow if it is big enough. When you set the environment in which a function will run, you're telling it to assume the environment is, e.g. your table env. Now, whenever it calls a function, instead of attempting to find the function in _G, it attempts to find it in env. env is empty, therefore it is going to fail. This is why it fails to load your code. root is a constant variable that contains the root element. It is the same as calling getRootElement, although faster since the value is already stored, you don't need to call the function over and over. I assume root is not defined in your environment table, and that's your problem.

Link to comment

But if locals are not stored in the new environment, they won't be deleted after you clear that table, right?

Try using table.copy (env=table.copy(_G)), no need for a recursive copy. table.copy

Okay, I'll try to do that.

EDIT: It's working by copying the table, but clearing the table does not affect variables..

Link to comment
EDIT: It's working by copying the table, but clearing the table does not affect variables..

I cannot reproduce that - local variables stay in the scope of the function created by loadstring and shouldn't exist outside of it. Do you have some code that I can use to attempt to reproduce your issue?

Try using table.copy (env=table.copy(_G)), no need for a recursive copy. table.copy

Yes, this is an alternative, but the code loaded at env will be able to access functions that were defined in the default environment, and as such, it may call these functions and cause issues.

Link to comment
EDIT: It's working by copying the table, but clearing the table does not affect variables..

I cannot reproduce that - local variables stay in the scope of the function created by loadstring and shouldn't exist outside of it. Do you have some code that I can use to attempt to reproduce your issue?

Try using table.copy (env=table.copy(_G)), no need for a recursive copy. table.copy

Yes, this is an alternative, but the code loaded at env will be able to access functions that were defined in the default environment, and as such, it may call these functions and cause issues.

I have a map that sets a variables after u hit a marker, to make u have to follow an order. But after map restart, that variable is still set so u can just go for the last marker.

I'll send u that map.

Link to comment
@Bonsai, so how did you solve the problem?

After some testing, I'm not sure its solved at all. :/

When I do this environment stuff and e.g. create an marker this happens:

Script of a map contains

if source == marker1 onClientMarkerHit 

Nothing happens.

I checked the userdata of the source and marker1, and they are not equal, even though its the only marker being created.

I don't understand how this happened..

Link to comment
i don't have issues with that though. Markers work as intended.

Ye, I found out its not the markers. Its the source. The source of that onClientMarkerHit event is always the local player. It's probably because the function that loads the script is triggered by an event and the source of that event is indeed the localPlayer. I've no idea how to get that right..

Link to comment

Well you are loading code from a lua file, can't you just simply use brackets and send the data? :)

I mean

  
-- Client Sided 
local Bonsai = [[  
-- Your code  
-- blah  
-- bah  
]]  
  
addEventHandler("onResourceStart",getRootElement(), 
function () 
triggerServerEvent ("onSendCode", getLocalPlayer(), Bonsai ) 
end) 
  

  
-- Server Sided  
addEvent ("onSendCode", true ) 
addEventHandler ("onSendCode", getRootElement(),  
function(commandstring) 
        local notReturned 
        local commandFunction, errorMsg = loadstring("return "..commandstring) 
        if errorMsg then 
            notReturned = true 
            commandFunction, errorMsg = loadstring(commandstring) 
        end 
        if errorMsg then 
            outputDebugString(errorMsg); 
            return 
        end 
        results = { pcall(commandFunction) } 
        if not results[1] then 
            return 
        end 
        if not notReturned then 
            local resultsString = "" 
            local first = true 
            for i = 2, #results do 
                if first then 
                    first = false 
                else 
                    resultsString = resultsString..", " 
                end 
                local resultType = type(results[i]) 
                if isElement(results[i]) then 
                    resultType = "element:"..getElementType(results[i]) 
                end 
                resultsString = resultsString..tostring(results[i]).." ["..resultType.."]" 
            end 
            outputDebugString(errorMsg); 
        elseif not errorMsg then 
        outputChatBox("See? It works", getRootElement(), 255, 255, 0, false ) 
        end 
end) 

Link to comment

@Saml1er, would totally be the same.

@Bonsai, in fact, you're getting userdata of 000001 (or similar) when using markers, right? That's root. You have to use rawget within the __index and specify source, root, resourceRoot, localPlayer, etc in the metatable. You have to return them in rawget if your key is "source", ...

P.S. Thanks to Arezu for the way of fixing the issue.

Link to comment
At least it seems to be fixable. Even though I'm not sure how to do what you said there.

yes, it's fixable, I'll ask Arezu if I may share the way with you, and if yes - i'll give you the code.

Well thanks, but it's not too bad if he doesn't want to.

I really want to understand how it works, especially what's causing the problem.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...