fix formatting in lua require and better error handling with dofile,loadfile,etc

This commit is contained in:
Evil Factory
2022-05-04 08:50:17 -03:00
parent 7a6ddccbb7
commit bbea195e7d
6 changed files with 148 additions and 169 deletions
@@ -3224,7 +3224,14 @@ namespace Barotrauma
return; return;
} }
GameMain.LuaCs.Lua.DoString(string.Join(" ", args)); try
{
GameMain.LuaCs.Lua.DoString(string.Join(" ", args));
}
catch(Exception ex)
{
GameMain.LuaCs.HandleException(ex);
}
})); }));
commands.Add(new Command("cl_cs", "cs_cl: runs a string on the client", (string[] args) => commands.Add(new Command("cl_cs", "cs_cl: runs a string on the client", (string[] args) =>
{ {
@@ -1243,7 +1243,14 @@ namespace Barotrauma
commands.Add(new Command("lua", "lua: runs a string", (string[] args) => commands.Add(new Command("lua", "lua: runs a string", (string[] args) =>
{ {
GameMain.LuaCs.Lua.DoString(string.Join(" ", args)); try
{
GameMain.LuaCs.Lua.DoString(string.Join(" ", args));
}
catch (Exception ex)
{
GameMain.LuaCs.HandleException(ex);
}
})); }));
commands.Add(new Command("cs", "cs: runs a string", (string[] args) => commands.Add(new Command("cs", "cs: runs a string", (string[] args) =>
{ {
@@ -16,7 +16,7 @@ namespace Barotrauma
Globals = setup.lua.Globals; Globals = setup.lua.Globals;
} }
public DynValue DoString(string code) => setup.DoString(code); public DynValue DoString(string code) => setup.lua.DoString(code);
} }
} }
} }
@@ -7,113 +7,114 @@ using MoonSharp.Interpreter;
namespace Barotrauma namespace Barotrauma
{ {
class LuaRequire { class LuaRequire
private Script lua { get; set; } {
private Dictionary<string, DynValue> loadedModules { get; set; } private Script lua { get; set; }
private Dictionary<string, DynValue> loadedModules { get; set; }
private bool getExistingReturnValue(string moduleName, ref DynValue returnValue) private bool GetExistingReturnValue(string moduleName, ref DynValue returnValue)
{
return loadedModules.TryGetValue(
moduleName,
out returnValue
);
}
private string fixContentPackagePath(string contentPackagePath)
{
contentPackagePath = Path.TrimEndingDirectorySeparator(
new FileInfo(contentPackagePath) // filelist.xml
.Directory
.FullName
.CleanUpPathCrossPlatform()
);
return contentPackagePath;
}
private string getContentPackagePath(string path)
{
IEnumerable<ContentPackage> allContentPackages = ContentPackageManager.AllPackages;
foreach (ContentPackage contentPackage in allContentPackages)
{
string contentPackagePath = fixContentPackagePath(contentPackage.Path);
if (path.StartsWith(contentPackagePath))
{ {
return contentPackagePath; return loadedModules.TryGetValue(
moduleName,
out returnValue
);
}
private string FixContentPackagePath(string contentPackagePath)
{
contentPackagePath = Path.TrimEndingDirectorySeparator(
new FileInfo(contentPackagePath) // filelist.xml
.Directory
.FullName
.CleanUpPathCrossPlatform()
);
return contentPackagePath;
}
private string GetContentPackagePath(string path)
{
IEnumerable<ContentPackage> allContentPackages = ContentPackageManager.AllPackages;
foreach (ContentPackage contentPackage in allContentPackages)
{
string contentPackagePath = FixContentPackagePath(contentPackage.Path);
if (path.StartsWith(contentPackagePath))
{
return contentPackagePath;
}
}
// Return null if we can't find a content package that
// this module belongs to.
return null;
}
private string GetContentPackagePath(string moduleName, Table environment)
{
string filePath = lua.Options
.ScriptLoader
.ResolveModuleName(
moduleName,
environment
);
filePath = Path.TrimEndingDirectorySeparator(
new FileInfo(filePath)
.Directory
.FullName
.CleanUpPathCrossPlatform()
);
return GetContentPackagePath(filePath);
}
private void SaveReturnValue(string moduleName, DynValue returnValue)
{
loadedModules[moduleName] = returnValue;
}
private void ExecuteModule(string moduleName, Table environment, ref DynValue returnValue)
{
DynValue loadFunc = lua.RequireModule(
moduleName,
environment
);
string packagePath = GetContentPackagePath(
moduleName,
environment
);
returnValue = lua.Call(
loadFunc,
packagePath
);
}
// 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 = null;
Table environment = globalContext ?? lua.Globals;
if (GetExistingReturnValue(moduleName, ref returnValue))
return returnValue;
ExecuteModule(moduleName, environment, ref returnValue);
if (
returnValue == null
|| returnValue.IsNil()
|| returnValue.IsVoid()
)
returnValue = DynValue.NewBoolean(true);
SaveReturnValue(moduleName, returnValue);
return returnValue;
}
public LuaRequire(Script lua)
{
this.lua = lua;
loadedModules = new Dictionary<string, DynValue>();
} }
}
// Return null if we can't find a content package that
// this module belongs to.
return null;
} }
private string getContentPackagePath(string moduleName, Table environment)
{
string filePath = lua.Options
.ScriptLoader
.ResolveModuleName(
moduleName,
environment
);
filePath = Path.TrimEndingDirectorySeparator(
new FileInfo(filePath)
.Directory
.FullName
.CleanUpPathCrossPlatform()
);
return getContentPackagePath(filePath);
}
private void saveReturnValue(string moduleName, DynValue returnValue)
{
loadedModules[moduleName] = returnValue;
}
private void executeModule(string moduleName, Table environment, ref DynValue returnValue)
{
DynValue loadFunc = lua.RequireModule(
moduleName,
environment
);
string packagePath = getContentPackagePath(
moduleName,
environment
);
returnValue = lua.Call(
loadFunc,
packagePath
);
}
// 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 = null;
Table environment = globalContext ?? lua.Globals;
if (getExistingReturnValue(moduleName, ref returnValue))
return returnValue;
executeModule(moduleName, environment, ref returnValue);
if (
returnValue == null
|| returnValue.IsNil()
|| returnValue.IsVoid()
)
returnValue = DynValue.NewBoolean(true);
saveReturnValue(moduleName, returnValue);
return returnValue;
}
public LuaRequire(Script lua)
{
this.lua = lua;
loadedModules = new Dictionary<string, DynValue>();
}
}
} }
@@ -245,80 +245,36 @@ namespace Barotrauma
public static void PrintCsMessage(object message) => PrintMessageBase("[CS] ", message, "Null"); public static void PrintCsMessage(object message) => PrintMessageBase("[CS] ", message, "Null");
public static void PrintLogMessage(object message) => PrintMessageBase("[LuaCs LOG] ", message, "Null"); public static void PrintLogMessage(object message) => PrintMessageBase("[LuaCs LOG] ", message, "Null");
private DynValue DoString(string code, Table globalContext = null, string codeStringFriendly = null)
{
try
{
return lua.DoString(code, globalContext, codeStringFriendly);
}
catch (Exception e)
{
HandleException(e);
}
return null;
}
private DynValue DoFile(string file, Table globalContext = null, string codeStringFriendly = null) private DynValue DoFile(string file, Table globalContext = null, string codeStringFriendly = null)
{ {
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null; if (!LuaCsFile.CanReadFromPath(file))
{
throw new ScriptRuntimeException($"dofile: File access to {file} not allowed.");
}
if (!LuaCsFile.Exists(file)) if (!LuaCsFile.Exists(file))
{ {
HandleException(new Exception($"dofile: File {file} not found.")); throw new ScriptRuntimeException($"dofile: File {file} not found.");
return null;
} }
try return lua.DoFile(file, globalContext, codeStringFriendly);
{
return lua.DoFile(file, globalContext, codeStringFriendly);
}
catch (Exception e)
{
HandleException(e);
}
return null;
}
private DynValue LoadString(string file, Table globalContext = null, string codeStringFriendly = null)
{
try
{
return lua.LoadString(file, globalContext, codeStringFriendly);
}
catch (Exception e)
{
HandleException(e);
}
return null;
} }
private DynValue LoadFile(string file, Table globalContext = null, string codeStringFriendly = null) private DynValue LoadFile(string file, Table globalContext = null, string codeStringFriendly = null)
{ {
if (!LuaCsFile.IsPathAllowedLuaException(file, false)) return null; if (!LuaCsFile.CanReadFromPath(file))
{
throw new ScriptRuntimeException($"loadfile: File access to {file} not allowed.");
}
if (!LuaCsFile.Exists(file)) if (!LuaCsFile.Exists(file))
{ {
HandleException(new Exception($"loadfile: File {file} not found.")); throw new ScriptRuntimeException($"loadfile: File {file} not found.");
return null;
} }
try return lua.LoadFile(file, globalContext, codeStringFriendly);
{
return lua.LoadFile(file, globalContext, codeStringFriendly);
}
catch (Exception e)
{
HandleException(e);
}
return null;
} }
public object CallLuaFunction(object function, params object[] arguments) public object CallLuaFunction(object function, params object[] arguments)
{ {
try try
@@ -435,8 +391,8 @@ namespace Barotrauma
lua.Globals["loadfile"] = (Func<string, Table, string, DynValue>)LoadFile; lua.Globals["loadfile"] = (Func<string, Table, string, DynValue>)LoadFile;
lua.Globals["require"] = (Func<string, Table, DynValue>)require.Require; lua.Globals["require"] = (Func<string, Table, DynValue>)require.Require;
lua.Globals["dostring"] = (Func<string, Table, string, DynValue>)DoString; lua.Globals["dostring"] = (Func<string, Table, string, DynValue>)lua.DoString;
lua.Globals["load"] = (Func<string, Table, string, DynValue>)LoadString; lua.Globals["load"] = (Func<string, Table, string, DynValue>)lua.LoadFile;
lua.Globals["CsScript"] = CsScript; lua.Globals["CsScript"] = CsScript;
lua.Globals["LuaUserData"] = UserData.CreateStatic<LuaUserData>(); lua.Globals["LuaUserData"] = UserData.CreateStatic<LuaUserData>();
@@ -116,16 +116,24 @@ namespace Barotrauma
if (write) if (write)
{ {
if (CanWriteToPath(path)) if (CanWriteToPath(path))
{
return true; return true;
}
else else
{
GameMain.LuaCs.HandleException(new Exception("File access to \"" + path + "\" not allowed.")); GameMain.LuaCs.HandleException(new Exception("File access to \"" + path + "\" not allowed."));
}
} }
else else
{ {
if (CanReadFromPath(path)) if (CanReadFromPath(path))
{
return true; return true;
}
else else
{
GameMain.LuaCs.HandleException(new Exception("File access to \"" + path + "\" not allowed.")); GameMain.LuaCs.HandleException(new Exception("File access to \"" + path + "\" not allowed."));
}
} }
return false; return false;