🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Lua - limiting available functions

Started by
11 comments, last by Wormy Hellcar 20 years, 7 months ago
The thing I want to do is simple. Limit the C functions that can be called from a certain script. For example script1 can use functions 1 through 10 and script2 can use 11 through 15. The reason is simple enough. I don''t want my AI scripts to be able to do things my game scripts can do and same with menus. I haven''t seen this mentioned anywhere in the docs or from other resources, but it may have slipped by me. Basically I want the user (end) to be able to script things themselves such as AI scripting (ala BG) except not be able to do things they shouldn''t like create items and generally cheat (also like in BG) Thanks in advance.
I used to be indecisive, but now I''m not so sure.
Advertisement
Personally, I use the tolua package for automatically generating the Lua bindings for my code. The way tolua works is that entities for export (functions, class definitions, constants, globals, enums, etc.) are declared in a package file, which is processed by the tolua executable to construct a .CPP file to be compiled and linked with the application.

The way this generated code is used is that tolua generates two functions--tolua_PACKAGENAME_open() and tolua_PACKAGENAME_close()--which are used to load and unload the various bindings.

In my game, I implement functionality hiding by calling tolua_XXX_open() and tolua_XXX_close() at appropriate times. For instance, all map generation is performed via script. During the map generation phase of level loading, I execute the function tolua_MapBuilding_open() to expose the map generation library to script. After the map is constructed, tolua_MapBuilding_close() will undo the bindings so that AI and event scripts can not (accidentally or intentionally) call MapBuilding functions and fuxxor the map.

Alternatively, you could make use of multiple Lua states, each state possessing a portion of the script interface, and each state associated with some task of the game. In my game, were I to use such a method, I would have one Lua state associated with MapBuilding, one associated with monster AI, and so on. I have not experimented with this method at all, so I honestly can not say how well it would work. Theoretically, I would say it should work just fine, but...


Josh
vertexnormal AT linuxmail DOT org

Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.
Cool.
Well tolua seems to do everything I want it to do, but I'm having a little trouble with it as it doesn't generate a _close function for a package.

EDIT: I'm just about to use tolua++
Hopefully it'll fix this.
I was using tolua because I couldn't get the the ++ site because of ISP problems.
It's still not working but I managed to get it from a friend. I'll report back later today

[edited by - Wormy Hellcar on November 12, 2003 11:01:11 PM]
I used to be indecisive, but now I''m not so sure.
quote: Original post by Wormy Hellcar
Well tolua seems to do everything I want it to do, but I''m having a little trouble with it as it doesn''t generate a _close function for a package.


Hmmm... I dunno why not.

Truthfully, I am using Lua 4.0, as my project was far too advanced by the time 5 came out, for me to relish the thought of switching. I can not honestly say whether or not tolua for 5 does things differently.

However (and again, this is speaking from the perspective of 4.0) it shouldn''t be too difficult (just laborious) to write your own close function. Basically, tolua creates a bunch of usertypes for the entities you export, and tolua_XXX_open() registers all of these various user types. All tolua_XXX_close() consists of is a long list of
lua_pushnil(tolua_S); lua_setglobal(tolua_S,"USERTYPENAMEHERE"); 


statements, one for each user data registered. If nothing else, you could do this by hand. (Very tedious, especially as your script interface increases in complexity; a macro would save some time, but still a major PITA.)

Anyway, good luck, and keep us posted on how it goes for you.


Josh
vertexnormal AT linuxmail DOT org

Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.
Well I''ve made a couple of discoveries.
I compiled two versions of the lua lib, aux lib, tolua lib and tolua exe for both versions 4 and 5.

Version 4
Generates the close function as expected.

Version 5
Does not generate the close function.

Furthermore writing some closing code for version 5 still lets you call that function from lua even though you closed it.

ie.
using lua_pushnil(tolua_S); lua_setglobal(tolua_S,"GetMenu");
then doing dostring(L, "GetMenu();"); will enter the GetMenu() function in your code while in 4.0 it doesn''t.

So I guess it''s 4.0 for me.

Thanks for the help.
I used to be indecisive, but now I''m not so sure.
While it's not really completely on topic it doesn't really warrant starting a new one.

I'm having a little problem with using tolua and default values.

Basically I have a class 'obj' and a constant instance called 'obj_self'. Now if I have a function like this

void DoSomething(obj = obj_self);

In the package and I use tolua it generates the code, but I have to manually go through and change certain lines from

*((obj*) tolua_getusertype(tolua_S,1,(void*)&obj_self));
to
*((obj*) tolua_getusertype(tolua_S,1,obj_self));

I can use a replace all to do it but it still is pretty annoying. Do you have any idea why this would be happening?

Here's the code relating to this.

Package file code
class obj {};const obj obj_self;void DoSomething(obj = obj_self);


C++ header
class obj {public:	...};extern const obj obj_self;

With obj_self being declared in a cpp file.

EDIT: Fixed up code tags (hopefully!)

[edited by - Wormy Hellcar on November 14, 2003 6:46:57 AM]

[edited by - Wormy Hellcar on November 14, 2003 6:51:06 AM]
I used to be indecisive, but now I''m not so sure.
I fixed the problem in the last post by just declaring obj_self etc as void* and adding a void* constructor to the obj class. Not very safe but easier than editting the tolua source.

Now I have another problem.

If I do something such as
foo(bar)
where foo has been declared as
void foo(obj)
and bar has not been declared, tolua 'crashes' because it tries to dereference a null pointer.
From what I can see it shouldn't do this as it does a check with tolua_noobj which I would have thought would return true if the userdata pointer was null. I guess I'll have to check the source and see what's up with it.

EDIT: It seemed to be occuring only on functions with default values. ie
decleration: foo(bar = default)
usage: foo(jim)
Where jim hasn't been used (ie, a nil value) would return a null pointer and then be dereferenced. I simply put a check for a nil value in the tolua_touserdata function (not tolua_noobj as I originally, mistakenly thought). Hopefully there won't be any side effects.


The immediate thing that came to mind when I thought of side effects were char* strings.

ie with the function void DoSomething(char* name = "jim")

But with the following code in a script it acts as it should

Command           -> value   - text------------------------------------DoSomething("");  -> nonnull - ""DoSomething(bar); -> null    - ""bar = "foo";DoSomething(bar); -> nonnull - "foo"DoSomething();    -> nonnull - "jim" 


EDIT2: Fixed up table (I never learn...)

[edited by - Wormy Hellcar on November 14, 2003 11:47:54 PM]

[edited by - Wormy Hellcar on November 14, 2003 11:49:07 PM]
I used to be indecisive, but now I''m not so sure.
Heh heh. Looks like it''s easier not to reply to this thread, but to just sit back and watch you as you work it out.

Anyway, I''m glad you''re getting it figured out. Keep us posted on how it goes.



Josh
vertexnormal AT linuxmail DOT org

Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.
Well I have tolua and lua working pretty much as I'd like it to bar two problems.

The first is a memory leak with tolua. I'm using Paul "Midnight" Nettle's memory manager (http://www.flipcode.com/askmid/archives.shtml) which is a bit old and has a few bugs but nothing I can't work around easily.

Now, basically any functions that return a class by value cause a memory leak.
eg in the tolua pkg file

obj Blah();

Will cause an obj to be floating around in the ether when the program exits. I'm pretty sure I'm closing down properly and I saw something about this in another thread (http://www.gamedev.net/community/forums/topic.asp?topic_id=163092) but with no definite answer. I'm going to try asking on the lua mailing list but I figured I'd ask here as well.

I see from your site you have a working game so I figured you might have fixed this memory leak and could help me.
I'm assuming you're using tolua for that project and not something else. Also I made a small test project using tolua 5.0 and lua 5.0 and the memory leak still occured.

I really don't want to have to do things by reference
ie have void Blah(obj&);
in the package then use
something = Blah(something) in the lua code. That just looks horrible for a simple return value.

Here's a sample from the memleaks.log file with one memory leak at exit.
Alloc.   Addr       Size       Addr       Size                        BreakOn BreakOn              Number Reported   Reported    Actual     Actual     Unused    Method  Dealloc Realloc Allocated by ------ ---------- ---------- ---------- ---------- ---------- -------- ------- ------- ----------------000147 0x04978470 0x00000008 0x04978460 0x00000028 0x00000000 new         N       N    ai.cpp(00147)::??And the code at that linevoid* toluaI_clone = new obj(toluaI_ret);  

So basically it creates an obj to push onto the stack as userdata, yet doesn't clean it up later on.

Note that the size difference is just due to padding (I think)


The other problem is that I want to overload a classes operator, but it doesn't seem to want to let me do it.
I basically want to be able to compare one tolua class instance with another tolua class instance and have it enter C code.
ie. I have a constant obj classe obj_invalid and an obj obj_self.
If I do

if(obj_self == obj_invalid) then
-- blah
end

I want it to enter the overloaded function I specify. However tolua doesn't seem to let you overload == or != functions and I couldn't find much info on how to go about using tags from the lua docs. I know I can implement it in a different way such as
obj_self:compare(obj_invalid) but I'm trying to make the scripting as simple as possible and that looks much worse than a simple ==.


Well hopefully you (or anyone else) can help a lua-newb like myself or point me in the right direction
Thanks again in advance.


Oh and I figured out how to fix the void* problem elegently. I just added a void* operator (duh!)
I don't know why I didn't think of that when I was replacing obj_self with (void*)&obj_self (they were around the wrong way in ony of my previous posts)

Now I just select my package project, click build all (then click yes to all those annoying file changed dialogues!) and switch back and can run without having to do lots of replaces.
When I get my scripting syntax complete I'll probably remove the void* operator though to avoid any accidental conversions.

EDIT: I don't think I'll ever get away with a single post that's ever correctly formatted. Why don't these boards have a preview button? Or do they and I'm just completely clueless?

EDIT: Third time lucky...

[edited by - Wormy Hellcar on November 15, 2003 8:17:17 AM]

[edited by - Wormy Hellcar on November 15, 2003 8:18:10 AM]

[EDIT: fixed formatting, it was messing with the page]

[edited by - Andrew Russell on November 16, 2003 8:40:18 AM]
I used to be indecisive, but now I''m not so sure.
quote: Original post by Wormy Hellcar
The first is a memory leak with tolua. I''m using Paul "Midnight" Nettle''s memory manager (http://www.flipcode.com/askmid/archives.shtml) which is a bit old and has a few bugs but nothing I can''t work around easily.

Now, basically any functions that return a class by value cause a memory leak.
eg in the tolua pkg file

obj Blah();

Will cause an obj to be floating around in the ether when the program exits. I''m pretty sure I''m closing down properly and I saw something about this in another thread (http://www.gamedev.net/community/forums/topic.asp?topic_id=163092) but with no definite answer. I''m going to try asking on the lua mailing list but I figured I''d ask here as well.

*snip*


That memory leak has never been a problem for me, as I don''t have anything that returns an object by value. All object creation in my game is handled by centralized allocators, which manage lists of objects and maintain pools of unused objects, to avoid constant allocation and deletion. Any exported function to the script interface calls these allocators to obtain a pointer to a created object.

quote:
The other problem is that I want to overload a classes operator, but it doesn''t seem to want to let me do it.
I basically want to be able to compare one tolua class instance with another tolua class instance and have it enter C code.
ie. I have a constant obj classe obj_invalid and an obj obj_self.


From what I understand, there is no way to do this purely through the tolua interface, though I could be wrong. Instead, what you have to do is implement tag methods in script assigned to the tags of your defined types. Even then, you are limited to tag methods for addition, subtraction, multiplication, division, and power for mathematical operations; that is, there is no tag method corresponding to +=, ++, !=, == or anything like that.

That is just a limitation you have to accept in exchange for a simple and lightweight embedded language such as Lua, I''m afraid. More complicated features mean larger executables, steeper learning curve, etc... If you wish your embedded language to have all the features of C++, you might as well just embed C++.

Anyway, good luck and I hope you continue to get this figured out.

Josh
vertexnormal AT linuxmail DOT org

Check out Golem: Lands of Shadow, an isometrically rendered hack-and-slash inspired equally by Nethack and Diablo.

This topic is closed to new replies.

Advertisement