Laurens Posted September 15, 2011 Share Posted September 15, 2011 Hi, I have decided to embrace Lua for the sake of getting a game done and stop fussing about proper architecture. To this end, I would like to have an executable similar to the engine-provided executable that just runs start.lua. With a twist. I would like to use CEGUI and I need to bootstrap it to Leadwerks in C++. No problems there, but how do I get Leadwerks to run start.lua similar to what the provided executable does? It seems the Lua API provides a dofile() method but this does not seem to be exposed to the engine. Thanks! Quote Link to comment Share on other sites More sharing options...
Rick Posted September 15, 2011 Share Posted September 15, 2011 In C++: luaL_loadfile (lua_start_var, "start.lua")) I think the lua state variable is exposed right? Quote Link to comment Share on other sites More sharing options...
Canardia Posted September 15, 2011 Share Posted September 15, 2011 Basically you don't even need to call any Lua scripts. I noticed in my LEBuilder GameLib FPS template that all Lua entity scripts just run fine. So you can do you main loop with C++ and the entity scripts in Lua, that's the best way to do it. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Rick Posted September 15, 2011 Share Posted September 15, 2011 I honestly wouldn't. I was/am big on "thingoids" because they are cool and easy for other people to plug and play, but coming up with the design and interactions between all these to make a complete game is more of the same of fussing about proper design and given his comment I have decided to embrace Lua for the sake of getting a game done and stop fussing about proper architecture. using the main Lua file is the best way to go. You can sub in entity scripts for certain things but if finishing a game is your main priority over coming up with a cool design, then don't fully rely on entity scripts as you'll get lost in design. I speak from my experience in this area. I was against the main Lua file and all for entity scripts because it was fun making those interactions, but to do it for every aspect of a game will eat up a ton of time and make you "hack" around things to get a game done. It's just easier to code in your main Lua file and supplement with the entity scripts. I use my entity scripts like classes. Then I code most of my game in a C fashion in Lua and found I was able to produce something much faster and easier. Just my experience I speak of though. Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 16, 2011 Author Share Posted September 16, 2011 Thanks for the fast replies, that should work perfectly! I use my entity scripts like classes. Then I code most of my game in a C fashion in Lua and found I was able to produce something much faster and easier. Just my experience I speak of though. This is the route I intend to take as well, using the main Lua file. I just needed to setup CEGUI in C++. Otherwise CEGUI supports Lua as well so I hope I don't need to get back to C++ again. Quote Link to comment Share on other sites More sharing options...
Rick Posted September 16, 2011 Share Posted September 16, 2011 I found this method works great, but a warning from my experience. Test change you make in Lua often. The debugging in Lua is horrible. The errors you'll get sometimes will have nothing to do with what is actually wrong. I know this can happen in other languages but I've found it is worse in Lua (with LE at least). On average every function I add I'll test right away if possible because a missed end or messed up variable and you'll be hosed. I can't even imagine adding a big framework of code and then run it. In C++ I don't have an issue with doing that as I can fix the few errors I've made and recompile. In Lua doing such a thing could have your scratching your head for hours. Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 29, 2011 Author Share Posted September 29, 2011 Hi again, I have only been able to try this last night when I found out this command is not included by the standard engine header. Did you inlcude the Lua headers for this Rick? Thanks! Quote Link to comment Share on other sites More sharing options...
Rick Posted September 29, 2011 Share Posted September 29, 2011 I did, BUT note that Josh is using LuaJIT 1.1.6 and not just normal Lua. For my purpose of loading a DLL and calling Lua methods from the DLL I had to use LuaJIT or I ran into problems with playing nicely with LE's Lua implementation. Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 29, 2011 Author Share Posted September 29, 2011 Excellent, I'll try that when I get back home tonight. Thanks! Quote Link to comment Share on other sites More sharing options...
Rick Posted September 29, 2011 Share Posted September 29, 2011 Note the last time I linked Lua with LE there were some naming conflicts because Josh used/exposed the same name of functions that Lua has. I remember this being a pain. If what you are trying to do is use CEGUI from Lua, you can create a DLL that has all the CEGUI stuff and expose functions to be called from Lua, and even call functions from your DLL back to Lua. This is what I'm doing with RakNet and it's working well (now that I know he's using LuaJIT and not straight Lua). This might be really nice with a GUI as you could register the name of a Lua function to act as an event callback. This is an example of the DLL I'm using. #define LUA_API_EXP __declspec(dllexport) #include "RakPeerInterface.h" #include "MessageIdentifiers.h" #include "BitStream.h" #include "RakNetTypes.h" // MessageID #include <string> #include <map> #include <iostream> #include <fstream> using namespace std; extern "C" { #include "lua.h" #include "lualib.h" #include "lauxlib.h" // prevents the function name from being mangled LUA_API_EXP int luaopen_raknet(lua_State *L); } RakNet::RakPeerInterface *peer = RakNet::RakPeerInterface::GetInstance(); RakNet::Packet *packet; RakNet::SystemAddress serverAddress; map<RakNet::MessageID, string> luaHandlers; static int NetBindMessageEvent(lua_State* L) { int msgID = luaL_checknumber(L, 1); const char* luaFunctionName = luaL_checkstring(L, 2); string functionName = luaFunctionName; // link the lua function name to this msg id luaHandlers[msgID] = functionName; return 0; } static const luaL_reg netLib[] = { {"Connect", NetConnect}, {"Update", NetUpdate}, {"BindMessageEvent", NetBindMessageEvent}, {"CreateBitStream", NetCreateBitStream}, {"Send", NetSend}, {"WriteBitStream", NetWriteBitStream}, {"ReadBitStream", NetReadBitStream}, {"Disconnect", NetDisconnect}, {NULL, NULL} }; // lua calls this to open the library LUA_API_EXP int luaopen_raknet (lua_State *L) { if(!log1) { myfile.open ("RakNetLuaLog.txt", ios::out | ios::app); log1 = true; } WriteLog("Inside luaopen_raknet"); luaL_openlib(L, "raknet", netLib, 0); return 1; } Then in Lua you do: ID_CONNECTION_REQUEST_ACCEPTED = 16 -- Load RakNet package package.loadlib("C:\\Leadwerks Engine SDK\\RakNetLua.dll", "luaopen_raknet")() function ConnectionSuccess() end raknet.BindMessageEvent(ID_CONNECTION_REQUEST_ACCEPTED, "ConnectionSuccess") I also expose an Update() function in the DLL and call that every frame from Lua. The Update method for me is looking for network packets and when it finds a packet that matches a message id I've registered calls the Lua function I associated with it. This should work with a GUI also. Can't remember what is all used with CEGUI to make it draw and collect input so not sure if this way would work or not. Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 29, 2011 Author Share Posted September 29, 2011 That's pretty sweet (and quite mind bending having never look like anything like it before) Rick. If what you are trying to do is use CEGUI from Lua, you can create a DLL that has all the CEGUI stuff and expose functions to be called from Lua, and even call functions from your DLL back to Lua. CEGUI has a built-in Lua interpreter so I can already do that, my main concern was calling a Lua script from C++ that is not an entity script. I want to do as little as possible in C++ unless it is absolutely required. The main loop would look like this: while (!AppTerminate()) { UpdateFramework(); // Run game.lua (facade for all game logic, written as Lua scripts as well. You can compare this with a game logic class' Update() method) RenderFramework(); glPixelStoref(0x806E, 0); glPixelStoref(GL_PACK_ROW_LENGTH, 0); glPixelStoref(GL_UNPACK_ROW_LENGTH, 0); CEGUI::System::getSingleton().renderGUI(); Flip(); } This way I can stricly contain game logic in Lua and keep everything else contained in the C++ binary which is a clean seperation that I like. Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 29, 2011 Author Share Posted September 29, 2011 So I have been trying to get this working for the past few hours. I have gotten to the point where I can build the application without compilation errors but I am getting one upon linking: build/Debug/MinGW-Windows/_ext/1186093/Script.o:/src/Script.cpp:6: undefined reference to `luaL_loadfile(lua_State*, char const*)' I am obviously missing some DLL. Did you have to compile LuaJIT and reference the resulting "lua51.dll" in your project? Quote Link to comment Share on other sites More sharing options...
Rick Posted September 29, 2011 Share Posted September 29, 2011 I compiled the source of LuaJIT into my project. LuaJIT I don't think has anything to do with normal lua so don't need the DLL. A linker error shouldn't have anything to do with a missing DLL though. If anything it would be missing lib, but if you compile LuaJIT source right into your project then there is no .lib file to reference. I would assume LuaJIT has that function but not sure as I'm not using that function and not at home. Can you search the LuaJIT source to see if that function is in there? Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 29, 2011 Author Share Posted September 29, 2011 Hi Rick, I'm flustered, no matter how I compile or reference LuaJIT in my project, it is not compiling any .lib. All I end up with is "lua51.dll" and "luajit.exe". There is nothing to link to. I have to assume that when you build your project, there has to be some kind of .lib to link to, even though VS copies it to the appropriate directories for you. Is there anything in your project's directory that slightly resembles the lib? The function is in fact present in the source distribution, in "lauxlib.h" to be precise so that shouldn't be the problem. Quote Link to comment Share on other sites More sharing options...
Rick Posted September 29, 2011 Share Posted September 29, 2011 I actually included all the header and source files into my VS project. There was a thing where I had to copy and paste some dasm files in another folder to the rest of the header and source files to get that to compile. There also is an int main() in the Lua source that I had to find and commented out to make it compile. I didn't go the route of compiling LuaJIT into a lib and then using that lib in my project. It's small enough where I just compiled the source along with my project. And yeah this stuff can get very frustrated. You don't know how angry I was that my RakNet Lua DLL was working with the lua.exe program but not LE before Josh mentioned that it's not normal Lua that LE uses it's LuaJIT. LuaJIT is just close enough to actual Lua where some stuff was working, some stuff had small differences, and some stuff didn't work at all. Quote Link to comment Share on other sites More sharing options...
Laurens Posted September 30, 2011 Author Share Posted September 30, 2011 I guess I can give that a try. I wish Josh would have just exposed the LuaJIT methods to LE though, this is extremely painful. Thanks for all the help! I'll let you know how it turns out tonight. Quote Link to comment Share on other sites More sharing options...
Laurens Posted October 1, 2011 Author Share Posted October 1, 2011 Well, don't I feel silly. After getting some help on the LuaHub forums I managed to get MinGW to compile the import library but it turns out the compiler is fine with linking against a DLL so I didn't need it. The root cause of the problem was incorrectly including the header: #include "lauxlib.h" should be extern "C" { #include "lauxlib.h" } I was unaware of the fact you needed to include C code like that. Anyway, it is compiling and running now, sort of. At the point where I run the file, I get a PANIC: unprotected error in call to Lua API (attempt to call a string value) though, but at least I got it running using Leadwerks' Lua state. Quote Link to comment Share on other sites More sharing options...
Laurens Posted October 2, 2011 Author Share Posted October 2, 2011 So I finally figured this thing out. I used the code I found here: http://cc.byexamples.com/2008/11/19/lua-stack-dump-for-c/ to debug the Lua stack at various points in the application. This is my final main loop: Script* s = new Script(reinterpret_cast<lua_State*> (GetLuaState()), "Scripts/Game/game.lua"); while (!AppTerminate()) { UpdateFramework(); s->Run(); // calls luaL_dofile RenderFramework(); glPixelStoref(0x806E, 0); glPixelStoref(GL_PACK_ROW_LENGTH, 0); glPixelStoref(GL_UNPACK_ROW_LENGTH, 0); CEGUI::System::getSingleton().renderGUI(); Flip(); } delete s; It turns out only the first call to to s->Run() failed, and all others were fine. Appearantly simply calling CreateFramework() does not complete the initialization. Upon calling RenderFramework() the engine loads more resources and all subsequent calls to s->Run() work fine. Perhaps the Lua state is not initialized up until the first call to RenderFramework()? Anyhow, it is working perfectly fine now. Thanks for the help! Quote Link to comment Share on other sites More sharing options...
Rick Posted October 2, 2011 Share Posted October 2, 2011 Did you get CEGUI calling Lua functions? I know you mentioned CEGUI has that built in, which I was thinking about today. I assume that means CEGUI has Lua compiled into it. Be sure it's LuaJIT and not normal Lua or else the method calls would probably fail as the lua state variable between the 2 are slightly different. Quote Link to comment Share on other sites More sharing options...
Laurens Posted October 2, 2011 Author Share Posted October 2, 2011 Hi Rick, CEGUI can indeed call Lua functions but it does so in its own state. It has Lua 5.0.1 compiled into it and passing Leadwerks' Lua state as a parameter to the construction of the scripting module fails. Communication between CEGUI and Leadwerks is therefore not possible (so you can't call engine methods from the CEGUI state and vice versa) so next order of business is trying to recompile CEGUI and roll in LuaJIT as a replacement to "vanilla" Lua. Quote Link to comment Share on other sites More sharing options...
Laurens Posted October 4, 2011 Author Share Posted October 4, 2011 I have spend the last two evenings trying to get CEGUI to compile, even without replacing the Lua implementations but slew of dependencies is hellish and I think I am going to give up on this one. I vaguely remember you having similar problems when you were trying to create a single DLL that contained all the dependencies for Leadwerks. In the spirit of moving forward I think am I going to hardcode the event handlers, which allows me to still define layouts in XML, just not the interactions. Quote Link to comment Share on other sites More sharing options...
Rick Posted October 4, 2011 Share Posted October 4, 2011 Yeah see I'm not a fan of CEGUI anymore. To me it's an example of everything wrong with open source because of dependency hell like you say. Quote Link to comment Share on other sites More sharing options...
Gabriel Posted December 1, 2011 Share Posted December 1, 2011 So I finally figured this thing out. I used the code I found here: http://cc.byexamples.com/2008/11/19/lua-stack-dump-for-c/ to debug the Lua stack at various points in the application. This is my final main loop: Script* s = new Script(reinterpret_cast<lua_State*> (GetLuaState()), "Scripts/Game/game.lua"); while (!AppTerminate()) { UpdateFramework(); s->Run(); // calls luaL_dofile RenderFramework(); glPixelStoref(0x806E, 0); glPixelStoref(GL_PACK_ROW_LENGTH, 0); glPixelStoref(GL_UNPACK_ROW_LENGTH, 0); CEGUI::System::getSingleton().renderGUI(); Flip(); } delete s; It turns out only the first call to to s->Run() failed, and all others were fine. Appearantly simply calling CreateFramework() does not complete the initialization. Upon calling RenderFramework() the engine loads more resources and all subsequent calls to s->Run() work fine. Perhaps the Lua state is not initialized up until the first call to RenderFramework()? Anyhow, it is working perfectly fine now. Thanks for the help! Hi now : Run is not a methode of Script why is removed in my version 2.5 ? Thank Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.