lua script loader Topic is solved

Problems building or running the engine, queries about how to use features etc.
slapin
Bronze Sponsor
Bronze Sponsor
Posts: 250
Joined: Fri May 23, 2025 5:04 pm
x 16

lua script loader

Post by slapin »

Hi, all!
I try to implement Lua script loader for lua's require() function for it to use Ogre's resource function.
The problem is that script lib I use has a lot of scripts and extensively use require() with lots of subdirectories, so script paths ending up like tests/common/ops.lua which is not compatible with Ogre's resource system which flattens everything out if I add subdirectories to locations or just knows nothing about subdirectories. So the question is how can I make ResourceGroupManager let me open subdirectory paths?

slapin
Bronze Sponsor
Bronze Sponsor
Posts: 250
Joined: Fri May 23, 2025 5:04 pm
x 16

Re: lua script loader

Post by slapin »

I found super cool thing now which let me make lua's require work via Ogre's resource system.

Code: Select all

		Ogre::ResourceGroupManager::getSingleton().createResourceGroup(
			"LuaScripts", false);
		Ogre::ResourceGroupManager::getSingleton().addResourceLocation(
			"./lua-scripts", "FileSystem", "LuaScripts", true,
			true);

in OgreBites::ApplicationContext derived class (App) method locateResources()
and I have LuaScripts section in resource.cfg.
The loader function:

Code: Select all

int luaLibraryLoader(lua_State *L)
{
	int i;
	if (!lua_isstring(L, 1)) {
		luaL_error(
			L,
			"luaLibraryLoader: Expected string for first parameter");
	}

std::string libraryFile = lua_tostring(L, 1);
std::cout << libraryFile << std::endl;
// In order to be compatible with the normal Lua file loader,
// translate '.' to the file system seperator character.
// In this case (An ogre resource) '/'
while (libraryFile.find('.') != std::string::npos)
	libraryFile.replace(libraryFile.find('.'), 1, "/");

libraryFile += ".lua";
std::cout << libraryFile << std::endl;
Ogre::StringVectorPtr scripts =
	Ogre::ResourceGroupManager::getSingleton().listResourceNames(
		"LuaScripts", false);
std::vector<Ogre::String> &strings = *scripts;
for (i = 0; i < strings.size(); i++)
	std::cout << strings[i] << std::endl;

if (0 && !Ogre::ResourceGroupManager::getSingleton()
		  .resourceExistsInAnyGroup(libraryFile)) {
	// Could not find the file.
	std::string errMessage = "\n  no file '" + libraryFile +
				 "' found in Ogre resource archives.";
	lua_pushstring(L, errMessage.c_str());
} else {
	Ogre::DataStreamList streams =
		Ogre::ResourceGroupManager::getSingleton().openResources(
			"*.lua", "LuaScripts");
	Ogre::DataStreamPtr stream =
		Ogre::ResourceGroupManager::getSingleton().openResource(
			libraryFile, "LuaScripts");
	Ogre::String script = stream->getAsString();
	if (luaL_loadbuffer(L, script.c_str(), script.length(),
			    libraryFile.c_str())) {
		luaL_error(
			L,
			"Error loading library '%s' from resource archive.\n%s",
			libraryFile.c_str(), lua_tostring(L, -1));
	}
}
return 1;
}
[code]

loader "installer" function:

[code]
static void installLibraryLoader(lua_State *L)
{
	// Insert the c++ func 'luaLibraryLoader' into package.loaders.
	// Inserted at the start of the table in order to take precedence.
	lua_getglobal(L, "table");
	lua_getfield(L, -1, "insert");
	lua_remove(L, -2); // table
	lua_getglobal(L, "package");
	lua_getfield(L, -1, "searchers");
	lua_remove(L, -2); // package
	lua_pushnumber(L, 1); // index where to insert into loaders table
	lua_pushcfunction(L, luaLibraryLoader);
	if (lua_pcall(L, 3, 0, 0))
		Ogre::LogManager::getSingleton().stream() << lua_tostring(L, 1);
}

Lua init code:

Code: Select all

	installLibraryLoader(L);
	lua_pop(L, 1);

after base libs and it works perfectly well.

All the struggle was mainly for stuff like https://github.com/astrochili/narrator which help a lot with dialogue systems.

To make it work the following init sequence was necessary:

Code: Select all

	luaopen_base(L);
	luaopen_table(L);
	luaopen_package(L);
	luaL_requiref(L, "table", luaopen_table, 1);
	lua_pop(L, 1);
	luaL_requiref(L, "math", luaopen_math, 1);
	lua_pop(L, 1);
	luaL_requiref(L, "package", luaopen_package, 1);
	lua_pop(L, 1);
	luaL_requiref(L, "string", luaopen_string, 1);
	lua_pop(L, 1);
	luaL_requiref(L, "io", luaopen_io, 1);
	lua_pop(L, 1);
	luaL_requiref(L, "lpeg", luaopen_lpeg, 1); // just compile source with lua and extern "C" the function
	lua_pop(L, 1);
	installLibraryLoader(L);
	lua_pop(L, 1);

To write working code I was heavily digging https://github.com/merlinblack/Game-Eng ... source.cpp.