Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

thehurricane

multiple Lua states and tolua?

This topic is 5737 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

For each object(enemy, door, switch, button, etc.)in my sidescroller I''m thinking about having an individual Lua state so that it''s variables and functions are completely contained. Then each object will be able to receive a message like "collision" and another object and react according to its Lua scripts...I''ve used ToLua, a binding tool that maps C++ classes to Lua automatically before, but my question is...would it be overkill and inefficient to use ToLua and all the multiple Lua states? Each time you use ToLua you have to initialize it with a Lua state, so on the creation of an object I''d have to bind ToLua to it...in essence each state is then carrying the weight of userdata tags and functions defined by ToLua, but all that info is the same...should I find a better way?

Share this post


Link to post
Share on other sites
Advertisement
if you want to group an object''s variables and functions, why not make them all elements in a table, rather than globals in a lua_State? using multiple states solely for scoping is overkill.


How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites
I understand why you would question as to why even bother using seperate Lua states, but I was posing it as a hypothetical question, not knowing the penalty or tradeoff involved, and whether or not the idea is even worth pursuing...yes it would be easy to accumulate all objects in one script, but there are also serious benefits beyond scoping for multiple states.

Share this post


Link to post
Share on other sites
Even with the tags etc, the lua_State isnt going to be very big, so unless your sidescroller will instansiate a really huge number of scripted objects i dont think it will be a problem.

I also use multiple lua_States, mostly because it makes everything extremelly simple, and i definetly want the scripts themselves to be as simple as possible.

Share this post


Link to post
Share on other sites
Aren''t there other disadvantages of multiple states? eg. you no longer have ''global'' variables (which might be considered a good thing in C++ but is perhaps an unnecessary precaution in Lua).

Can anyone list the benefits? The variables and functions can be self-contained no matter how many states you have, cos you can just store them in an object/table. I don''t really see the point, to be honest.

PS. See also here.

[ MSVC Fixes | STL Docs | SDL | Game AI | Sockets | C++ Faq Lite | Boost
Asking Questions | Organising code files | My stuff | Tiny XML | STLPort]

Share this post


Link to post
Share on other sites
As mentioned above, it is perfectly possible to keep functions in one state, but it requires that the scripts are actually written as such. Now, this may just be a few braces around the function declarations etc, but even this can be considered a slight complication of the scripts.(the whole idea of scripting is to make the game modifiable(?) by people who can hardly program, right?)

Also if you put them in the same lua_State then you cant really delete a script(or can you?), so the functions will stay resident.(this is probably neglectable compared to the space overhead of multiple lua_State though .

Furthermore with multiple states, its impossible for one script to mess with the others, which might be beneficial, and its possible to implement a "security model" where not all type of scripts have access to the whole script API(ie avoid player AI scripts suddenly spawning items etc), by simply registering only allowed functions to the lua_State.

On the downside it means no global functions(at least not without registering them to *all* the lua_States), which is a bit of problem Also if scripts are only run once, the overhead of registering functions might be unacceptable...

Actually, if it wasnt for the security model stuff, id probably would also be using a single lua_State(actually now that im considering it, i think i probably will anyway).. oh damn, back to the code, luckily its only a few changes

EDIT: Just thought about one more issue regarding this.
I suppose that the way one would stuff everything into one state would be something like this:

charm_person
{
timeleft=100,
init = function (target) ... dostuff ...,
update = function (deltatime) ... etc ,
destroy = function () ...
}

But what happens when we have multiple charm spells? The charm spell script file will be loaded multiple times, overwriting the old one. Im sure this can solved by playing around with tables as objects, but it seems to me that it will make the scripting more complicated?

[edited by - ziphnor on March 31, 2003 2:08:00 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Ziphnor
Also if you put them in the same lua_State then you cant really delete a script(or can you?), so the functions will stay resident.(this is probably neglectable compared to the space overhead of multiple lua_State though .


Of course you can; just remove references to them. The garbage collector will remove them.

quote:

Furthermore with multiple states, its impossible for one script to mess with the others, which might be beneficial, and its possible to implement a "security model" where not all type of scripts have access to the whole script API(ie avoid player AI scripts suddenly spawning items etc), by simply registering only allowed functions to the lua_State.



True, though if everyone's playing around in their own table, authors would have to go out of their way to mess with stuff they shouldn't.


quote:

EDIT: Just thought about one more issue regarding this.
I suppose that the way one would stuff everything into one state would be something like this:

charm_person
{
timeleft=100,
init = function (target) ... dostuff ...,
update = function (deltatime) ... etc ,
destroy = function () ...
}



Yup, that works well. Of course, it's really "charm_person =" and then the rest of that stuff.

quote:

But what happens when we have multiple charm spells? The charm spell script file will be loaded multiple times, overwriting the old one. Im sure this can solved by playing around with tables as objects, but it seems to me that it will make the scripting more complicated?



Err... do you actually have your engine parse the script every time someone executes the spell? just load them the first time, or only when the script is not found (using the newindex metamethod, for instance). And even if the script does execute more than once, it's still not a problem, since it just overwrites the functions with identical ones.
[edited by - ziphnor on March 31, 2003 2:08:00 PM]



How appropriate. You fight like a cow.

[edited by - sneftel on March 31, 2003 3:08:25 PM]

Share this post


Link to post
Share on other sites
quote:

Of course you can; just remove references to them. The garbage collector will remove them.



Can you remove an entire table like this?(im pretty new to lua)
ie charm_person = nil or something similar?

quote:

True, though if everyone''s playing around in their own table, authors would have to go out of their way to mess with stuff they shouldn''t.



Generally i think that its pretty bad that one script might actually delete something in another, leading to weird bugs.
But you are right, its more of theoretical problem

quote:

Err... do you actually have your engine parse the script every time someone executes the spell? just load them the first time, or only when the script is not found (using the newindex metamethod, for instance).



The (mostly precompiled) script is loaded into memory only once(when someone request that it be loaded), and if someone later requests the same script, a new lua_State is created from the same "buffer"(by lookup in a hashtable). If the script isnt precompiled then yes it will be reparsed(from memory) since i still havent found out how to compile from a lua file to a buffer at runtime.
After that calls can be made to the functions in the script from the outside( like init/update/destroy etc).

quote:

And even if the script does execute more than once, it''s still not a problem, since it just overwrites the functions with identical ones.



Thats true if the scripts are stateless, that is not necesarily the case. For example the charm_person spell has a timeleft stat, that for example might be decremented by the update function(ie a countdown until the spell ends). If we "redo" the definition then the timeleft variable will also be reset.
No matter what to different charm_person spells might be in use, requiring two different timeleft variables.

I really would prefer doing it with a single lua_State but i think the table syntax is a bit ugly, and i really want to keep my scripts clean and accesible.

Share this post


Link to post
Share on other sites
What about a table generator function?


function charmPerson(caster, target)
spell = {}
spell.caster = caster
spell.target = target
spell.someStateVar = 3
function spell:update()
self.someStateVar = 5
self.target.charmed = true
end
return spell
end

-- now you can do this:

myCastingOfCharmPerson = charmPerson("dave", "fred")
myCastingOfCharmPerson.update()


EDIT: oh, and despite how it looks, in memory there's only one copy of update() for all charmPerson spells that are ever created. Yay Lua.


How appropriate. You fight like a cow.

[edited by - sneftel on March 31, 2003 4:39:38 PM]

[edited by - sneftel on March 31, 2003 4:40:05 PM]

Share this post


Link to post
Share on other sites
For a game I am working I created a model to make it easy to self contain scripts and make it easy to free all the data once i freed a script. I didn't use multiple lua states and I can't imagine why you would need to.

Basically what I did is create a C function call SetPackage which creates a table (if it isn't already created) and then sets a metatable for the global table. This metatable is responsible for looking up a variable/function in the package table if it is not found in the global table. To prevent the global table from getting polluted anytime a value is trying to be set in the global table, it is instead set in the package table. So... to run a create all you need to do is call:


    
lua->setPackage("scriptfilename_lua");
lua->doFile("scriptfilename");
lua->pushString("Hello computer"); //parameter to HelloWorld Function

lua->callLuaFunction("HelloWorld"); //Will call HelloWorld in the script that was just executed.

lua->closePackage();

//Trying to call the function now will fail...

lua->pushString("Hello computer"); //parameter to HelloWorld Function

lua->callLuaFunction("HelloWorld"); //Will try to call HelloWorld in the current script but will fail.


lua->releasePackage("scriptfilename_lua"); //Will delete the table and all its variables and functions.




It is transparent to the script that all it's variables and functions are being self contained. When a C function calls a function in the current script it is unknowingly calling a function in the user package table. To delete a package you just set the table to null and the table and all it's values will get garbage collected.

If you need global variables to passed among multiple packages then you create another table in the global table when there is no current package set. You can call this table "Globals" or whatever and anytime a script needs to set a global all it has to do is Globals.keyname = "whatever".

I read over this thread quickly but I think this will help and it has worked great for me. And also note that I am using LUA 5.0.


--- COMPUTABILITY ---

[edited by - Computability on March 31, 2003 7:27:52 PM]

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!