Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lua emulating the require function

In the embeded lua environment (World of Warcraft - WoW) is missing the require function.

I want port one existing lua source code (an great OO-library) for the use it in the WoW. The library itself is relatively small (approx 8 small files) but of course it heavily uses the require.

World of Warcraft loads files and libraries by defining it in an XML file, like:

<Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
    <Script file="LibOne.lua"/>
    <Script file="LibTwo.lua"/>
</Ui>

but i don't know how the low level library manipulation is done in the WoW.

AFAIK in the WoW is missing even the package. table too. :(

So the question(s): For me, the streamlined way would be write an function which will emulate the require function using the interface available in WoW. The question is how. Could someone give me some directions?

Or as alternative, for the porting the mentioned existing source to WoW, I need replace the require Some.Other.Module lines in the lua sources to something what WoW will understand. What is the equivalent/replacement for such require Some.Module in the WoW?

How the WoW handles modules/libraries at low-level?

like image 586
cajwine Avatar asked Apr 26 '16 17:04

cajwine


People also ask

What does require () do in Lua?

Lua offers a higher-level function to load and run libraries, called require . Roughly, require does the same job as dofile , but with two important differences. First, require searches for the file in a path; second, require controls whether a file has already been run to avoid duplicating the work.

What is a Lua module?

To encapsulate data and functions, Lua uses modules. A Lua module is a regular Lua table that is used to contain functions and data. The table is declared local not to pollute the global scope: local M = {} -- private local message = "Hello world!" function M.


2 Answers

You could merge all files into one using one of the various amalgamation scripts, e.g. amalg. Then you can load this file and a stub that implements the require function using the usual WoW way:

<Ui xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
    <Script file="RequireStub.lua"/>
    <Script file="AllModules.lua"/><!-- amalgamated Lua modules -->
    <Script file="YourCode.lua"/>
</Ui>

The file RequireStub.lua could look like:

package = {}
local preload, loaded = {}, {
  string = string,
  debug = debug,
  package = package,
  _G = _G,
  io = io,
  os = os,
  table = table,
  math = math,
  coroutine = coroutine,
}
package.preload, package.loaded = preload, loaded


function require( mod )
  if not loaded[ mod ] then
    local f = preload[ mod ]
    if f == nil then
      error( "module '"..mod..[[' not found:
       no field package.preload[']]..mod.."']", 1 )
    end
    local v = f( mod )
    if v ~= nil then
      loaded[ mod ] = v
    elseif loaded[ mod ] == nil then
      loaded[ mod ] = true
    end
  end
  return loaded[ mod ]
end

This should emulate enough of the package library to get you a working require that loads modules in the amalgamated file. Different amalgamation scripts might need different bits from package, though, so you probably will have to take a look at the generated Lua source code.

And in the specific case of Coat you might need to implement stubs for other Lua functions as well. E.g. I've seen that Coat uses the debug library ...

like image 194
siffiejoe Avatar answered Sep 20 '22 14:09

siffiejoe


WoW environment doesn't have dofile or any other means to read external files at all. You need to explicitly mention all files that must be loaded in .toc file or .xml referenced from .toc.

You can then write your own implementation of require to maintain compatibility with your library, which would be quite trivial as it would only need to parse module name and retrieve it's content from modules.loaded table, but you'd still need to alter original source to make files register in that table and you'll need to manually arrange all files into correct order of loading.

Alternatively you can rearrange files into separate WoW-addons and use its own built-in Dependencies/OptionalDeps facilities or popular LibStub framework to handle loading order automatically.

like image 22
Oleg V. Volkov Avatar answered Sep 19 '22 14:09

Oleg V. Volkov