k i think i figured out how to load "libraries" without having to know of an exact location of the lua files. this replaces dofile() calls, which needs to know the way from root to where the files are in the mod dirs. it does this by using the cfile facilities to locate and open files independently of any known path. so essentially i load the lua code into a string. i then use loadstring to turn it into a lua chunk (which is essentially a code block). loadstring then returns a function that runs the block when called. to make things a little faster i made it so it only needs to read the file once, to generate the chunk function, and then it caches it into a table for later use.
i put the function at the head of the global init hook. i figure i can use it to chop up my script into manageable pieces and make things somewhat more modular, though its main purpose is to load libraries. id rather the scripting table had better facilities to load multiple files per hook. but this is a good interim solution. im still kind of concerned about cheating though. im not sure if script ran in this manor would get past anti-cheating checks if it were modified. i would assume those checks only apply to what is in the scripting.tbl and not lua files loaded by the table (and likewise lua files loaded by other lua files). something to think about anyway.
--function to load and run lua files
--takes string filename and boolean cacheonly
--cfile will try to find filename in all accesible locations and load it only if it hasnt done so already
--if cacheonly flag is set, code will be cached but not executed, good for inits. however it is ignored when calling an already cached chunk.
--returns true on success, false on failure to compile, or nil on failure to find/load file
chunck_cache = {}
function execute_lua_file(filename, cacheonly)
--dont reload chunks from file if they have already been loaded. because faster == badass
if chunck_cache[filename] then
chunck_cache[filename]()
return true
else
if cf.fileExists(filename, "", true) then
--open the file
local file = cf.openFile(filename, "r", "")
local fstring = file:read("*a") --load it all into a string
file:close()
if type(fstring) == "string" then
--use the string as a code chunk and convert it to function
local func, errorstring = loadstring(fstring, filename)
if type(func) == "function" then
--cache function
chunck_cache[filename] = func
--maybe execute
if not cacheonly then
chunck_cache[filename]()
end
return true
--compile error
elseif errorstring then
ba.warning("Error in '"..filename.."': "..errorstring)
return false
end
end
else --file not found error
ba.warning("File '"..filename.."' not found")
return nil
end
end
end
and all you have to do is call it with the name of the lua file you want to run
--call lua from file or chunk cache if file has already been loaded
execute_lua_file("somefile.lua")
--precache lua file for later execution
execute_lua_file("somefile.lua", true)
*edit: script updated for better error handling*