diff --git a/LuaBins/LuaInterface.dll b/LuaBins/LuaInterface.dll new file mode 100644 index 00000000..5e0b7b10 Binary files /dev/null and b/LuaBins/LuaInterface.dll differ diff --git a/LuaBins/lua51.dll b/LuaBins/lua51.dll new file mode 100644 index 00000000..86d15597 Binary files /dev/null and b/LuaBins/lua51.dll differ diff --git a/LuaBins/luanet.dll b/LuaBins/luanet.dll new file mode 100644 index 00000000..2772ba4b Binary files /dev/null and b/LuaBins/luanet.dll differ diff --git a/TShockAPI/Commands.cs b/TShockAPI/Commands.cs index 8c7eef08..45c95d6b 100644 --- a/TShockAPI/Commands.cs +++ b/TShockAPI/Commands.cs @@ -208,6 +208,10 @@ namespace TShockAPI add(Permissions.cfg, ServerInfo, "stats"); add(Permissions.converthardmode, ConvertCorruption, "convertcorruption"); add(Permissions.converthardmode, ConvertHallow, "converthallow"); + add(Permissions.runlua, RunLuaFile, "luarun"); + add(Permissions.runlua, RunLuaString, "lua"); + add(Permissions.runlua, ReloadLua, "luareload"); + add(Permissions.runlua, TestLuaHook, "testhook"); } public static bool HandleCommand(TSPlayer player, string text) @@ -325,6 +329,43 @@ namespace TShockAPI return c == ' ' || c == '\t' || c == '\n'; } + #region Lua Commands + + public static void TestLuaHook(CommandArgs args) + { + TShock.LuaLoader.HookCalls.OnHookTest(); + } + + public static void ReloadLua(CommandArgs args) + { + TShock.LuaLoader.LoadServerAutoruns(); + args.Player.SendMessage("Lua reloaded."); + } + + public static void RunLuaString(CommandArgs args) + { + + if (args.Parameters.Count < 1) + { + args.Player.SendMessage("Syntax: /lua "); + return; + } + + TShock.LuaLoader.RunLuaString(args.Parameters[0]); + args.Player.SendMessage("Lua run: " + args.Parameters[0]); + } + + public static void RunLuaFile(CommandArgs args) + { + if (args.Parameters.Count != 1) + { + args.Player.SendMessage("Syntax: /luarun "); + return; + } + TShock.LuaLoader.RunLuaFile(args.Parameters[0]); + } + #endregion + #region Account commands public static void AttemptLogin(CommandArgs args) @@ -1246,19 +1287,19 @@ namespace TShockAPI } } - private static void StartHardMode(CommandArgs args) - { - if (!TShock.Config.DisableHardmode) - WorldGen.StartHardmode(); - else - args.Player.SendMessage("Hardmode is disabled via config", Color.Red); - } + private static void StartHardMode(CommandArgs args) + { + if (!TShock.Config.DisableHardmode) + WorldGen.StartHardmode(); + else + args.Player.SendMessage("Hardmode is disabled via config", Color.Red); + } - private static void DisableHardMode(CommandArgs args) - { - Main.hardMode = false; - args.Player.SendMessage("Hardmode is now disabled", Color.Green); - } + private static void DisableHardMode(CommandArgs args) + { + Main.hardMode = false; + args.Player.SendMessage("Hardmode is now disabled", Color.Green); + } private static void ConvertCorruption(CommandArgs args) { diff --git a/TShockAPI/LuaSystem/LuaLoader.cs b/TShockAPI/LuaSystem/LuaLoader.cs new file mode 100644 index 00000000..78f41f20 --- /dev/null +++ b/TShockAPI/LuaSystem/LuaLoader.cs @@ -0,0 +1,191 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.ComponentModel; +using LuaInterface; + +namespace TShockAPI.LuaSystem +{ + public class LuaLoader + { + private readonly Lua _lua = null; + public string LuaPath = ""; + public string LuaAutorunPath = ""; + public LuaHookBackend HookBackend = new LuaHookBackend(); + public LuaHooks HookCalls = new LuaHooks(); + public Dictionary> Hooks = new Dictionary + >(); + public LuaLoader(string path) + { + _lua = new Lua(); + LuaPath = path; + LuaAutorunPath = Path.Combine(LuaPath, "autorun"); + SendLuaDebugMsg("Lua 5.1 (serverside) initialized."); + + if (!string.IsNullOrEmpty(LuaPath) && !Directory.Exists(LuaPath)) + { + Directory.CreateDirectory(LuaPath); + } + if (!string.IsNullOrEmpty(LuaAutorunPath) && !Directory.Exists(LuaAutorunPath)) + { + Directory.CreateDirectory(LuaAutorunPath); + } + + RegisterLuaFunctions(); + LoadServerAutoruns(); + } + + public void LoadServerAutoruns() + { + try + { + foreach (string s in Directory.GetFiles(LuaAutorunPath)) + { + SendLuaDebugMsg("Loading: " + s); + RunLuaFile(s); + } + } + catch (Exception e) + { + SendLuaDebugMsg(e.Message); + SendLuaDebugMsg(e.StackTrace); + } + } + + public void RunLuaString(string s) + { + try + { + _lua.DoString(s); + } + catch (LuaException e) + { + SendLuaDebugMsg(e.Message); + } + } + + public void RunLuaFile(string s) + { + try + { + _lua.DoFile(s); + } + catch (LuaException e) + { + SendLuaDebugMsg(e.Message); + } + } + + public void SendLuaDebugMsg(string s) + { + ConsoleColor previousColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("Lua: " + s); + Console.ForegroundColor = previousColor; + } + + public void RegisterLuaFunctions() + { + //I just added all the managers for Plugin Development. :) + //Feel free to remove any if you dont feel they are necessay + _lua["Players"] = TShock.Players; + _lua["Bans"] = TShock.Bans; + _lua["Warps"] = TShock.Warps; + _lua["Regions"] = TShock.Regions; + _lua["Backups"] = TShock.Backups; + _lua["Groups"] = TShock.Groups; + _lua["Users"] = TShock.Users; + _lua["Itembans"] = TShock.Users; + + + + LuaFunctions LuaFuncs = new LuaFunctions(this); + var LuaFuncMethods = LuaFuncs.GetType().GetMethods(); + foreach (System.Reflection.MethodInfo method in LuaFuncMethods) + { + _lua.RegisterFunction(method.Name, LuaFuncs, method); + } + + //Utils + Utils LuaUtils = new Utils(this); + var LuaUtilMethods = LuaUtils.GetType().GetMethods(); + foreach (System.Reflection.MethodInfo method in LuaUtilMethods) + { + _lua.RegisterFunction(method.Name, LuaUtils, method); + } + } + } + + public class LuaFunctions + { + LuaLoader Parent; + public LuaFunctions(LuaLoader parent) + { + Parent = parent; + } + + [Description("Prints a message to the console from the Lua debugger.")] + public void Print(string s) + { + ConsoleColor previousColor = Console.ForegroundColor; + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine(s); + Console.ForegroundColor = previousColor; + } + + [Description("Adds a hook that will trigger a function callback when activated.")] + public void HookAdd(string hook, string key, LuaFunction callback) + { + KeyValuePair internalhook = new KeyValuePair(hook, callback); + Parent.Hooks.Add(key, internalhook); + } + + [Description("Removes a hook from the hook table. Good for reloading stuff.")] + public void HookRemove(string key) + { + Parent.Hooks.Remove(key); + } + } + + public class LuaHookBackend + { + public void HookRun(string call, object parameters) + { + foreach (KeyValuePair> kv in TShock.LuaLoader.Hooks) + { + KeyValuePair hook = kv.Value; + if (call == hook.Key) + { + LuaFunction lf = hook.Value; + + if (lf != null) + { + try + { + lf.Call(parameters); + } + catch (LuaException e) + { + TShock.LuaLoader.SendLuaDebugMsg(e.Message); + } + } + } + } + } + } + + public class LuaHooks + { + [Description("Called on debug hook test.")] + public void OnHookTest() + { + object[] response = new object[2]; + response[0] = true; + response[1] = "Hook win!"; + TShock.LuaLoader.HookBackend.HookRun("HookTest", response); + } + } +} diff --git a/TShockAPI/Permissions.cs b/TShockAPI/Permissions.cs index 85c5bce4..d6680470 100644 --- a/TShockAPI/Permissions.cs +++ b/TShockAPI/Permissions.cs @@ -149,6 +149,8 @@ namespace TShockAPI [Description("Allow unrestricted Send Tile Square usage, for client side world editing")] public static readonly string allowclientsideworldedit; + [Description("User can execute Lua files from the hard disk and run Lua strings.")] public static readonly string + runlua; static Permissions() { diff --git a/TShockAPI/Properties/AssemblyInfo.cs b/TShockAPI/Properties/AssemblyInfo.cs index a4b97ef9..576805f2 100644 --- a/TShockAPI/Properties/AssemblyInfo.cs +++ b/TShockAPI/Properties/AssemblyInfo.cs @@ -49,4 +49,4 @@ using System.Runtime.InteropServices; // MMdd of the build [assembly: AssemblyVersion("3.4.5.0106")] -[assembly: AssemblyFileVersion("3.4.5.0106")] \ No newline at end of file +[assembly: AssemblyFileVersion("3.4.5.0106")] diff --git a/TShockAPI/StatTracker.cs b/TShockAPI/StatTracker.cs index 27ede224..353c8f19 100644 --- a/TShockAPI/StatTracker.cs +++ b/TShockAPI/StatTracker.cs @@ -86,7 +86,7 @@ namespace TShockAPI Environment.OSVersion + "&mono=" + Main.runningMono + "&port=" + Netplay.serverPort + "&plcount=" + TShock.Utils.ActivePlayers()); } - Log.ConsoleInfo("Stat Tracker: " + response + "\n"); + Log.ConsoleInfo("Stat Tracker: " + response); } catch (Exception e) { diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 7a7dbb5a..7f8571cf 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -31,6 +31,7 @@ using MaxMind; using Mono.Data.Sqlite; using MySql.Data.MySqlClient; using Rests; +using TShockAPI.LuaSystem; using Terraria; using TShockAPI.DB; using TShockAPI.Net; @@ -64,6 +65,7 @@ namespace TShockAPI public static RestManager RestManager; public static Utils Utils = new Utils(); public static StatTracker StatTracker = new StatTracker(); + public static LuaLoader LuaLoader; /// /// Called after TShock is initialized. Useful for plugins that needs hooks before tshock but also depend on tshock being loaded. @@ -418,8 +420,8 @@ namespace TShockAPI RestApi.Start(); StatTracker.CheckIn(); - FixChestStacks(); + LuaLoader = new LuaLoader(Path.Combine(".", "lua")); } private void FixChestStacks() diff --git a/TShockAPI/TShockAPI.csproj b/TShockAPI/TShockAPI.csproj index 461cff5e..25220392 100644 --- a/TShockAPI/TShockAPI.csproj +++ b/TShockAPI/TShockAPI.csproj @@ -53,6 +53,9 @@ ..\HttpBins\HttpServer.dll + + ..\LuaBins\LuaInterface.dll + ..\SqlBins\Mono.Data.Sqlite.dll @@ -107,6 +110,7 @@ + @@ -187,7 +191,7 @@ - +