Merge pull request #61 from Cintique/unstable-tests
Alter logic related to `require()`
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
local allPackages = ContentPackageManager.AllPackages
|
||||
local localPackages = ContentPackageManager.LocalPackages
|
||||
local LUA_MOD_REQUIRE_PATH = "/Lua/?.lua"
|
||||
local LUA_MOD_AUTORUN_PATH = "/Lua/Autorun"
|
||||
local LUA_MOD_FORCEDAUTORUN_PATH = "/Lua/ForcedAutorun"
|
||||
|
||||
local allPackages = ContentPackageManager.AllPackages
|
||||
local localPackages = ContentPackageManager.LocalPackages
|
||||
local enabledPackages = ContentPackageManager.EnabledPackages.All
|
||||
|
||||
local function EndsWith(str, suffix)
|
||||
@@ -30,52 +34,111 @@ local function RunFolder(folder, rootFolder, package)
|
||||
end
|
||||
end
|
||||
|
||||
local function assertTypes(expectedTypes, ...)
|
||||
local args = table.pack(...)
|
||||
assert(
|
||||
#args == #expectedTypes,
|
||||
string.format(
|
||||
"Assertion failed: incorrect number of args\n\texpected = %s\n\tgot = %s",
|
||||
#expectedTypes,
|
||||
#args
|
||||
)
|
||||
)
|
||||
for i = 1, #args do
|
||||
local arg = args[i]
|
||||
local expectedType = expectedTypes[i]
|
||||
assert(
|
||||
type(arg) == expectedType,
|
||||
string.format(
|
||||
"Assertion failed: incorrect argument type (arg #%d)\n\texpected = %s\n\tgot = %s",
|
||||
i,
|
||||
expectedType,
|
||||
type(arg)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
for contentPackage in enabledPackages do
|
||||
if contentPackage then
|
||||
local d = contentPackage.Path:gsub("\\", "/")
|
||||
d = d:gsub("/filelist.xml", "")
|
||||
local function ExecutionQueue()
|
||||
local queue = {}
|
||||
local function processQueueFIFO()
|
||||
while queue[1] ~= nil do
|
||||
RunFolder(
|
||||
table.unpack(
|
||||
table.remove(queue)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
local function queueExecutionFIFO(...)
|
||||
assertTypes(
|
||||
{ 'string', 'string', 'userdata' },
|
||||
...
|
||||
)
|
||||
table.insert(
|
||||
queue,
|
||||
table.pack(...)
|
||||
)
|
||||
end
|
||||
return queueExecutionFIFO, processQueueFIFO
|
||||
end
|
||||
|
||||
table.insert(package.path, (d .. "/Lua/?.lua"))
|
||||
local queueAutorun, processAutorun = ExecutionQueue()
|
||||
local queueForcedAutorun, processForcedAutorun = ExecutionQueue()
|
||||
|
||||
if File.DirectoryExists(d .. "/Lua/Autorun") then
|
||||
RunFolder(d .. "/Lua/Autorun", d, contentPackage)
|
||||
local function processPackages(packages, fn)
|
||||
for pkg in packages do
|
||||
if pkg then
|
||||
local pkgPath = pkg.Path
|
||||
:gsub("\\", "/")
|
||||
:gsub("/filelist.xml", "")
|
||||
fn(pkg, pkgPath)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
processPackages(
|
||||
enabledPackages,
|
||||
function(pkg, pkgPath)
|
||||
table.insert(package.path, pkgPath .. LUA_MOD_REQUIRE_PATH)
|
||||
local autorunPath = pkgPath .. LUA_MOD_AUTORUN_PATH
|
||||
if File.DirectoryExists(autorunPath) then
|
||||
queueAutorun(autorunPath, pkgPath, pkg)
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
-- we don't want to execute workshop ForcedAutorun if we have a local Package
|
||||
local executedLocalPackages = {}
|
||||
|
||||
for contentPackage in localPackages do
|
||||
if contentPackage then
|
||||
local d = contentPackage.Path:gsub("\\", "/")
|
||||
d = d:gsub("/filelist.xml", "")
|
||||
|
||||
table.insert(package.path, (d .. "/Lua/?.lua"))
|
||||
|
||||
if File.DirectoryExists(d .. "/Lua/ForcedAutorun") then
|
||||
RunFolder(d .. "/Lua/ForcedAutorun", d, contentPackage)
|
||||
|
||||
executedLocalPackages[contentPackage.Name] = true
|
||||
processPackages(
|
||||
localPackages,
|
||||
function(pkg, pkgPath)
|
||||
table.insert(package.path, pkgPath .. LUA_MOD_REQUIRE_PATH)
|
||||
local forcedAutorunPath = pkgPath .. LUA_MOD_FORCEDAUTORUN_PATH
|
||||
if File.DirectoryExists(forcedAutorunPath) then
|
||||
queueForcedAutorun(forcedAutorunPath, pkgPath, pkg)
|
||||
executedLocalPackages[pkg.Name] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
for contentPackage in allPackages do
|
||||
if contentPackage and executedLocalPackages[contentPackage.Name] == nil then
|
||||
local d = contentPackage.Path:gsub("\\", "/")
|
||||
d = d:gsub("/filelist.xml", "")
|
||||
|
||||
table.insert(package.path, (d .. "/Lua/?.lua"))
|
||||
|
||||
if File.DirectoryExists(d .. "/Lua/ForcedAutorun") then
|
||||
RunFolder(d .. "/Lua/ForcedAutorun", d, contentPackage)
|
||||
processPackages(
|
||||
allPackages,
|
||||
function(pkg, pkgPath)
|
||||
if not executedLocalPackages[pkg.Name] then
|
||||
table.insert(package.path, pkgPath .. LUA_MOD_REQUIRE_PATH)
|
||||
local forcedAutorunPath = pkgPath .. LUA_MOD_FORCEDAUTORUN_PATH
|
||||
if File.DirectoryExists(forcedAutorunPath) then
|
||||
queueForcedAutorun(forcedAutorunPath, pkgPath, pkg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
setmodulepaths(package.path)
|
||||
processAutorun()
|
||||
processForcedAutorun()
|
||||
|
||||
Hook.Add("stop", "luaSetup.stop", function ()
|
||||
print("Stopping Lua...")
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class LuaRequire {
|
||||
private Script lua { get; set; }
|
||||
private Dictionary<Tuple<string, Table>, DynValue> LoadedModules { get; set; }
|
||||
|
||||
private bool GetExistingReturnValue(Tuple<string, Table> key, ref DynValue returnValue) {
|
||||
return LoadedModules.TryGetValue(key, out returnValue);
|
||||
}
|
||||
|
||||
private void ExecuteModule(Tuple<string, Table> key, ref DynValue returnValue) {
|
||||
string moduleName = key.Item1;
|
||||
Table globalContext = key.Item2;
|
||||
returnValue = lua.Call(lua.RequireModule(moduleName, globalContext));
|
||||
LoadedModules[key] = returnValue;
|
||||
}
|
||||
|
||||
// Lua modules that have been previously loaded by require() will
|
||||
// not be loaded again; instead, their initial return value is
|
||||
// preserved and returned again on subsequent attempts.
|
||||
public DynValue Require(string moduleName, Table globalContext) {
|
||||
DynValue returnValue = DynValue.Nil;
|
||||
var key = new Tuple<string, Table>(moduleName, globalContext);
|
||||
|
||||
if (GetExistingReturnValue(key, ref returnValue)) return returnValue;
|
||||
ExecuteModule(key, ref returnValue);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public LuaRequire(Script lua) {
|
||||
this.lua = lua;
|
||||
LoadedModules = new Dictionary<Tuple<string, Table>, DynValue>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ namespace Barotrauma
|
||||
public LuaCsHook Hook { get; private set; }
|
||||
public LuaCsNetworking Networking { get; private set; }
|
||||
public LuaCsModStore ModStore { get; private set; }
|
||||
private LuaRequire require { get; set; }
|
||||
|
||||
public CsScriptLoader NetScriptLoader { get; private set; }
|
||||
public CsLua Lua { get; private set; }
|
||||
@@ -236,22 +237,18 @@ namespace Barotrauma
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private DynValue Require(string modname, Table globalContext)
|
||||
public DynValue Require(string moduleName, Table globalContexts)
|
||||
{
|
||||
try
|
||||
{
|
||||
return lua.Call(lua.RequireModule(modname, globalContext));
|
||||
|
||||
return require.Require(moduleName, globalContexts);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
HandleException(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public object CallLuaFunction(object function, params object[] arguments)
|
||||
{
|
||||
try
|
||||
@@ -310,6 +307,8 @@ namespace Barotrauma
|
||||
Lua = new CsLua(this);
|
||||
CsScript = new CsScriptRunner(this);
|
||||
|
||||
require = new LuaRequire(lua);
|
||||
|
||||
Game = new LuaGame();
|
||||
Networking = new LuaCsNetworking();
|
||||
Hook.Initialize();
|
||||
|
||||
Reference in New Issue
Block a user