[SOLVED] LUA: How to redirect "require" to load from packed file

Started by
0 comments, last by RabblePants 15 years, 4 months ago
Hi all, I'm busy integrating a packed-file reader into my engine, where all my assets (models, textures, scripts, etc) are shoved inside of one large file. At load time, I pull data from this file instead of doing regular file I/O from the individual files. The problem comes in with lua scripts - when I load up a script, I can correctly pull it from the my packed-file and load it using luaL_loadbuffer. However, if the script file has a "require" in it, the "require'd" file will not load as it is not physically present on my disk. So the question is - when a file is "require'd", how would I intercept the request for the new file to load, and return the actual script data? In other words, if Main.lua has the following line: require "GameScripts/MyScript" How could I catch that lua system wants to load "GameScripts/MyScript.lua", load the script data from MyGameAssets.pak, return a buffer to the script, and run as normal? Thanks in advance, Grafalgar [Edited by - Grafalgar on December 14, 2008 1:51:09 AM]
Advertisement
Well, that was pretty rough but I figured it out finally. Turns out that when you call "require" LUA accesses the global "package.loaders" table, which contains a list of functions which searches for and loads your particular lua file.

So, the trick is to add your own function at the end of package.loaders. If the file count not be loaded, push a new string onto the stack explaining why (or nil). If you could load it fine, just return the new buffer/file you loaded. That's all.

Example:

int MyLoader(lua_State* pState){	std::string module = lua_tostring(pState, 1);	module += ".lua";	const char* fullPath = module.c_str();	CMyFile file(fullPath);	int size = file.Size();	if(size > 0)	{		uint8* buffer = new uint8[size];		file.Read(buffer, size);		luaL_loadbuffer(pState, (const char*)buffer, size, fullPath);			}	else	{		std::string err = "\n\tError - MyLoader could not find ";		err += module;		err += ".";		lua_pushstring(err.c_str(), pState);	}		return 1;}void AddLoader(){	lua_getfield(mLUAState, LUA_GLOBALSINDEX, "package");	// push "package"	lua_getfield(mLUAState, -1, "loaders");					// push "package.loaders"	lua_remove(mLUAState, -2);								// remove "package"	// Count the number of entries in package.loaders.	// Table is now at index -2, since 'nil' is right on top of it.	// lua_next pushes a key and a value onto the stack.	int numLoaders = 0;	lua_pushnil(mLUAState);	while (lua_next(mLUAState, -2) != 0) 	{		lua_pop(mLUAState, 1);		numLoaders++;	}	lua_pushinteger(mLUAState, numLoaders + 1);	lua_pushcfunction(mLUAState, MyLoader);	lua_rawset(mLUAState, -3);	// Table is still on the stack.  Get rid of it now.	lua_pop(mLUAState, 1);}

This topic is closed to new replies.

Advertisement