make my eyes happier: Random is now deprecated, moved lots of code around in a way that makes more sense and better LuaUserData error handling
This commit is contained in:
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Barotrauma.Networking;
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class LuaSetup
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -416,7 +416,7 @@ namespace Barotrauma
|
||||
GameMain.Lua.Update();
|
||||
GameMain.Lua.hook.Call("think", new object[] { });
|
||||
performanceCounterTimer.Stop();
|
||||
LuaSetup.LuaTimer.LastUpdateTime = performanceCounterTimer.ElapsedMilliseconds;
|
||||
LuaTimer.LastUpdateTime = performanceCounterTimer.ElapsedMilliseconds;
|
||||
performanceCounterTimer.Reset();
|
||||
|
||||
Timing.Accumulator -= Timing.Step;
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using MoonSharp.Interpreter;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Networking;
|
||||
using System.Threading.Tasks;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class LuaSetup
|
||||
{
|
||||
partial class LuaGame
|
||||
{
|
||||
public bool IsDedicated
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.Server.ServerPeer is LidgrenServerPeer;
|
||||
}
|
||||
}
|
||||
|
||||
public ServerSettings ServerSettings => GameMain.Server.ServerSettings;
|
||||
|
||||
public static void SendMessage(string msg, ChatMessageType? messageType = null, Client sender = null, Character character = null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage(msg, messageType, sender, character);
|
||||
}
|
||||
|
||||
public static void SendMessage(string msg, int messageType, Client sender = null, Character character = null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage(msg, (ChatMessageType)messageType, sender, character);
|
||||
}
|
||||
|
||||
public static void SendTraitorMessage(Client client, string msg, string missionid, TraitorMessageType type)
|
||||
{
|
||||
GameMain.Server.SendTraitorMessage(client, msg, missionid, type);
|
||||
}
|
||||
|
||||
public static void SendDirectChatMessage(string sendername, string text, Character sender, ChatMessageType messageType = ChatMessageType.Private, Client client = null, string iconStyle = "")
|
||||
{
|
||||
|
||||
ChatMessage cm = ChatMessage.Create(sendername, text, messageType, sender, client);
|
||||
cm.IconStyle = iconStyle;
|
||||
|
||||
GameMain.Server.SendDirectChatMessage(cm, client);
|
||||
|
||||
}
|
||||
|
||||
public static void SendDirectChatMessage(ChatMessage chatMessage, Client client)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(chatMessage, client);
|
||||
}
|
||||
|
||||
public static void Log(string message, ServerLog.MessageType type)
|
||||
{
|
||||
GameServer.Log(message, type);
|
||||
}
|
||||
|
||||
public static void DispatchRespawnSub()
|
||||
{
|
||||
GameMain.Server.RespawnManager.DispatchShuttle();
|
||||
}
|
||||
|
||||
public static void StartGame()
|
||||
{
|
||||
GameMain.Server.StartGame();
|
||||
}
|
||||
|
||||
public static void EndGame()
|
||||
{
|
||||
GameMain.Server.EndGame();
|
||||
}
|
||||
|
||||
public void AssignOnClientRequestExecute(string names, object onExecute) => DebugConsole.AssignOnClientRequestExecute(names, (Client a, Vector2 b, string[] c) => { env.CallFunction(onExecute, new object[] { a, b, c }); });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
local compatibilityLib = {}
|
||||
|
||||
LuaUserData.AddMethod(LuaUserData.RegisterType("Barotrauma.LuaSetup+LuaUserData"), "AddCallMetaMember", function (v)
|
||||
LuaUserData.AddMethod(LuaUserData.RegisterType("Barotrauma.LuaUserData"), "AddCallMetaMember", function (v)
|
||||
print("AddCallMetaMember is deprecated, use debug.setmetatable instead.")
|
||||
end)
|
||||
|
||||
@@ -10,6 +10,18 @@ compatibilityLib.CreateVector2 = Vector2.__new
|
||||
compatibilityLib.CreateVector3 = Vector3.__new
|
||||
compatibilityLib.CreateVector4 = Vector4.__new
|
||||
|
||||
local luaRandom = {}
|
||||
|
||||
luaRandom.Range = function (min, max)
|
||||
return math.random(min, max)
|
||||
end
|
||||
|
||||
luaRandom.RangeFloat = function (min, max)
|
||||
return math.random() + math.random(min, max)
|
||||
end
|
||||
|
||||
compatibilityLib["Random"] = luaRandom
|
||||
|
||||
local luaPlayer = {}
|
||||
|
||||
luaPlayer.GetAllCharacters = function ()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,419 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using MoonSharp.Interpreter;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma.Items.Components;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using System.Reflection;
|
||||
using HarmonyLib;
|
||||
using MoonSharp.Interpreter.Interop;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
public partial class LuaTimer
|
||||
{
|
||||
public static long LastUpdateTime = 0;
|
||||
|
||||
public static double Time
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetTime();
|
||||
}
|
||||
}
|
||||
|
||||
public void Wait(object function, int millisecondDelay)
|
||||
{
|
||||
GameMain.Lua.hook.EnqueueTimedFunction((float)Timing.TotalTime + (millisecondDelay / 1000f), function);
|
||||
}
|
||||
|
||||
public static double GetTime()
|
||||
{
|
||||
return Timing.TotalTime;
|
||||
}
|
||||
|
||||
public static float GetUsageMemory()
|
||||
{
|
||||
Process proc = Process.GetCurrentProcess();
|
||||
float memory = MathF.Round(proc.PrivateMemorySize64 / (1024 * 1024), 2);
|
||||
proc.Dispose();
|
||||
|
||||
return memory;
|
||||
}
|
||||
}
|
||||
|
||||
partial class LuaFile
|
||||
{
|
||||
// TODO: SANDBOXING
|
||||
|
||||
public static bool IsPathAllowed(string path)
|
||||
{
|
||||
path = Path.GetFullPath(path).CleanUpPath();
|
||||
|
||||
if (path.StartsWith(Path.GetFullPath("Mods").CleanUpPath()))
|
||||
return true;
|
||||
|
||||
if (path.StartsWith(Path.GetFullPath("Submarines").CleanUpPath()))
|
||||
return true;
|
||||
|
||||
if (path.StartsWith(Path.GetFullPath("Data").CleanUpPath()))
|
||||
return true;
|
||||
|
||||
if (path.StartsWith(Path.GetFullPath("Lua").CleanUpPath()))
|
||||
return true;
|
||||
|
||||
if (path.StartsWith(Path.GetFullPath("Content").CleanUpPath()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsPathAllowedLuaException(string path)
|
||||
{
|
||||
if (IsPathAllowed(path))
|
||||
return true;
|
||||
else
|
||||
GameMain.Lua.HandleLuaException(new Exception("File access to \"" + path + "\" not allowed."));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string Read(string path)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(path))
|
||||
return "";
|
||||
|
||||
return File.ReadAllText(path);
|
||||
}
|
||||
|
||||
public static void Write(string path, string text)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(path))
|
||||
return;
|
||||
|
||||
File.WriteAllText(path, text);
|
||||
}
|
||||
|
||||
public static bool Exists(string path)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(path))
|
||||
return false;
|
||||
|
||||
return File.Exists(path);
|
||||
}
|
||||
|
||||
public static bool CreateDirectory(string path)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(path))
|
||||
return false;
|
||||
|
||||
Directory.CreateDirectory(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool DirectoryExists(string path)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(path))
|
||||
return false;
|
||||
|
||||
return Directory.Exists(path);
|
||||
}
|
||||
|
||||
public static string[] GetFiles(string path)
|
||||
{
|
||||
return Directory.GetFiles(path);
|
||||
}
|
||||
|
||||
public static string[] GetDirectories(string path)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(path))
|
||||
return new string[] { };
|
||||
|
||||
return Directory.GetDirectories(path);
|
||||
}
|
||||
|
||||
public static string[] DirSearch(string sDir)
|
||||
{
|
||||
if (!IsPathAllowedLuaException(sDir))
|
||||
return new string[] { };
|
||||
|
||||
List<string> files = new List<string>();
|
||||
|
||||
try
|
||||
{
|
||||
foreach (string f in Directory.GetFiles(sDir))
|
||||
{
|
||||
files.Add(f);
|
||||
}
|
||||
|
||||
foreach (string d in Directory.GetDirectories(sDir))
|
||||
{
|
||||
foreach (string f in Directory.GetFiles(d))
|
||||
{
|
||||
files.Add(f);
|
||||
}
|
||||
DirSearch(d);
|
||||
}
|
||||
}
|
||||
catch (System.Exception excpt)
|
||||
{
|
||||
Console.WriteLine(excpt.Message);
|
||||
}
|
||||
|
||||
return files.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
partial class LuaNetworking
|
||||
{
|
||||
public bool restrictMessageSize = true;
|
||||
|
||||
public Dictionary<string, object> LuaNetReceives = new Dictionary<string, object>();
|
||||
|
||||
#if SERVER
|
||||
[MoonSharpHidden]
|
||||
public void NetMessageReceived(IReadMessage netMessage, ClientPacketHeader header, Client client = null)
|
||||
{
|
||||
if (header == ClientPacketHeader.LUA_NET_MESSAGE)
|
||||
{
|
||||
string netMessageName = netMessage.ReadString();
|
||||
if (LuaNetReceives[netMessageName] is Closure)
|
||||
GameMain.Lua.CallFunction(LuaNetReceives[netMessageName], new object[] { netMessage, client });
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Lua.hook.Call("netMessageReceived", netMessage, header, client);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
[MoonSharpHidden]
|
||||
public void NetMessageReceived(IReadMessage netMessage, ServerPacketHeader header, Client client = null)
|
||||
{
|
||||
if (header == ServerPacketHeader.LUA_NET_MESSAGE)
|
||||
{
|
||||
string netMessageName = netMessage.ReadString();
|
||||
if (LuaNetReceives[netMessageName] is Closure)
|
||||
GameMain.Lua.lua.Call(LuaNetReceives[netMessageName], new object[] { netMessage, client });
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Lua.hook.Call("netMessageReceived", netMessage, header, client);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Receive(string netMessageName, object callback)
|
||||
{
|
||||
LuaNetReceives[netMessageName] = callback;
|
||||
}
|
||||
|
||||
public IWriteMessage Start(string netMessageName)
|
||||
{
|
||||
var message = new WriteOnlyMessage();
|
||||
#if SERVER
|
||||
message.Write((byte)ServerPacketHeader.LUA_NET_MESSAGE);
|
||||
#else
|
||||
message.Write((byte)ClientPacketHeader.LUA_NET_MESSAGE);
|
||||
#endif
|
||||
message.Write(netMessageName);
|
||||
return ((IWriteMessage)message);
|
||||
}
|
||||
|
||||
public IWriteMessage Start()
|
||||
{
|
||||
return new WriteOnlyMessage();
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
public void ClientWriteLobby(Client client) => GameMain.Server.ClientWriteLobby(client);
|
||||
|
||||
public void Send(IWriteMessage netMessage, NetworkConnection connection = null, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable)
|
||||
{
|
||||
if (connection == null)
|
||||
{
|
||||
foreach (NetworkConnection conn in Client.ClientList.Select(c => c.Connection))
|
||||
{
|
||||
GameMain.Server.ServerPeer.Send(netMessage, conn, deliveryMethod);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GameMain.Server.ServerPeer.Send(netMessage, connection, deliveryMethod);
|
||||
}
|
||||
}
|
||||
#else
|
||||
public void Send(IWriteMessage netMessage, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable)
|
||||
{
|
||||
GameMain.Client.ClientPeer.Send(netMessage, deliveryMethod);
|
||||
}
|
||||
#endif
|
||||
|
||||
public void RequestPostHTTP(string url, object callback, string data, string contentType = "application/json")
|
||||
{
|
||||
try
|
||||
{
|
||||
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
httpWebRequest.ContentType = contentType;
|
||||
httpWebRequest.Method = "POST";
|
||||
|
||||
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
|
||||
streamWriter.Write(data);
|
||||
|
||||
httpWebRequest.BeginGetResponse(new AsyncCallback((IAsyncResult result) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var httpResponse = httpWebRequest.EndGetResponse(result);
|
||||
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
||||
GameMain.Lua.hook.EnqueueFunction(callback, streamReader.ReadToEnd());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GameMain.Lua.hook.EnqueueFunction(callback, e.ToString());
|
||||
}
|
||||
}), null);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GameMain.Lua.hook.EnqueueFunction(callback, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void RequestGetHTTP(string url, object callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
|
||||
|
||||
httpWebRequest.BeginGetResponse(new AsyncCallback((IAsyncResult result) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var httpResponse = httpWebRequest.EndGetResponse(result);
|
||||
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
|
||||
GameMain.Lua.hook.EnqueueFunction(callback, streamReader.ReadToEnd());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GameMain.Lua.hook.EnqueueFunction(callback, e.ToString());
|
||||
}
|
||||
}), null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
GameMain.Lua.hook.EnqueueFunction(callback, e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateEntityEvent(INetSerializable entity, object[] extraData)
|
||||
{
|
||||
GameMain.NetworkMember.CreateEntityEvent(entity, extraData);
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
public void UpdateClientPermissions(Client client)
|
||||
{
|
||||
GameMain.Server.UpdateClientPermissions(client);
|
||||
}
|
||||
|
||||
public void RemovePendingClient(ServerPeer.PendingClient pendingClient, DisconnectReason reason, string msg)
|
||||
{
|
||||
GameMain.Server.ServerPeer.RemovePendingClient(pendingClient, reason, msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
public ushort LastClientListUpdateID
|
||||
{
|
||||
get { return GameMain.NetworkMember.LastClientListUpdateID; }
|
||||
set { GameMain.NetworkMember.LastClientListUpdateID = value; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LuaResult
|
||||
{
|
||||
object result;
|
||||
public LuaResult(object arg)
|
||||
{
|
||||
result = arg;
|
||||
}
|
||||
|
||||
public bool IsNull()
|
||||
{
|
||||
if (result == null)
|
||||
return true;
|
||||
|
||||
if (result is DynValue dynValue)
|
||||
return dynValue.IsNil();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool Bool()
|
||||
{
|
||||
if (result is DynValue dynValue)
|
||||
{
|
||||
return dynValue.CastToBool();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public float Float()
|
||||
{
|
||||
if (result is DynValue dynValue)
|
||||
{
|
||||
var num = dynValue.CastToNumber();
|
||||
if (num == null) { return 0f; }
|
||||
return (float)num.Value;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public double Double()
|
||||
{
|
||||
if (result is DynValue dynValue)
|
||||
{
|
||||
var num = dynValue.CastToNumber();
|
||||
if (num == null) { return 0f; }
|
||||
return num.Value;
|
||||
}
|
||||
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public string String()
|
||||
{
|
||||
if (result is DynValue dynValue)
|
||||
{
|
||||
var str = dynValue.CastToString();
|
||||
if (str == null) { return ""; }
|
||||
return str;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public object Object()
|
||||
{
|
||||
if (result is DynValue dynValue)
|
||||
{
|
||||
return dynValue.ToObject();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,485 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using FarseerPhysics.Dynamics;
|
||||
using Microsoft.Xna.Framework;
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class LuaGame
|
||||
{
|
||||
public bool IsSinglePlayer => GameMain.IsSingleplayer;
|
||||
public bool IsMultiplayer => GameMain.IsMultiplayer;
|
||||
public GameSettings GameSettings => GameMain.Config;
|
||||
|
||||
#if CLIENT
|
||||
public ChatBox ChatBox
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GameMain.IsSingleplayer)
|
||||
return GameMain.GameSession.CrewManager.ChatBox;
|
||||
else
|
||||
return GameMain.Client.ChatBox;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
public bool IsDedicated
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.Server.ServerPeer is LidgrenServerPeer;
|
||||
}
|
||||
}
|
||||
|
||||
public ServerSettings ServerSettings => GameMain.Server.ServerSettings;
|
||||
#endif
|
||||
|
||||
public bool allowWifiChat = false;
|
||||
public bool overrideTraitors = false;
|
||||
public bool overrideRespawnSub = false;
|
||||
public bool overrideSignalRadio = false;
|
||||
public bool disableSpamFilter = false;
|
||||
public bool disableDisconnectCharacter = false;
|
||||
public bool enableControlHusk = false;
|
||||
|
||||
public int mapEntityUpdateInterval
|
||||
{
|
||||
get { return MapEntity.MapEntityUpdateInterval; }
|
||||
set { MapEntity.MapEntityUpdateInterval = value; }
|
||||
}
|
||||
|
||||
public int gapUpdateInterval
|
||||
{
|
||||
get { return MapEntity.GapUpdateInterval; }
|
||||
set { MapEntity.GapUpdateInterval = value; }
|
||||
}
|
||||
|
||||
public HashSet<Item> updatePriorityItems = new HashSet<Item>();
|
||||
|
||||
public void AddPriorityItem(Item item)
|
||||
{
|
||||
updatePriorityItems.Add(item);
|
||||
}
|
||||
|
||||
public void RemovePriorityItem(Item item)
|
||||
{
|
||||
updatePriorityItems.Remove(item);
|
||||
}
|
||||
|
||||
public void ClearPriorityItem()
|
||||
{
|
||||
updatePriorityItems.Clear();
|
||||
}
|
||||
|
||||
public bool RoundStarted
|
||||
{
|
||||
|
||||
get
|
||||
{
|
||||
#if SERVER
|
||||
return GameMain.Server.GameStarted;
|
||||
#else
|
||||
return GameMain.Client.GameStarted;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public GameSession GameSession
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.GameSession;
|
||||
}
|
||||
}
|
||||
|
||||
public NetLobbyScreen NetLobbyScreen
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.NetLobbyScreen;
|
||||
}
|
||||
}
|
||||
|
||||
public GameScreen GameScreen
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.GameScreen;
|
||||
}
|
||||
}
|
||||
|
||||
public World World
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.World;
|
||||
}
|
||||
}
|
||||
|
||||
#if SERVER
|
||||
public ServerPeer Peer
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.Server.ServerPeer;
|
||||
}
|
||||
}
|
||||
#else
|
||||
public ClientPeer Peer
|
||||
{
|
||||
get
|
||||
{
|
||||
return GameMain.Client.ClientPeer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public void OverrideTraitors(bool o)
|
||||
{
|
||||
overrideTraitors = o;
|
||||
}
|
||||
|
||||
public void OverrideRespawnSub(bool o)
|
||||
{
|
||||
overrideRespawnSub = o;
|
||||
}
|
||||
|
||||
public void AllowWifiChat(bool o)
|
||||
{
|
||||
allowWifiChat = o;
|
||||
}
|
||||
|
||||
public void OverrideSignalRadio(bool o)
|
||||
{
|
||||
overrideSignalRadio = o;
|
||||
}
|
||||
|
||||
public void DisableSpamFilter(bool o)
|
||||
{
|
||||
disableSpamFilter = o;
|
||||
}
|
||||
|
||||
public void DisableDisconnectCharacter(bool o)
|
||||
{
|
||||
disableDisconnectCharacter = o;
|
||||
}
|
||||
|
||||
|
||||
public void EnableControlHusk(bool o)
|
||||
{
|
||||
enableControlHusk = o;
|
||||
}
|
||||
|
||||
public static void Explode(Vector2 pos, float range = 100, float force = 30, float damage = 30, float structureDamage = 30, float itemDamage = 30, float empStrength = 0, float ballastFloraStrength = 0)
|
||||
{
|
||||
new Explosion(range, force, damage, structureDamage, itemDamage, empStrength, ballastFloraStrength).Explode(pos, null);
|
||||
}
|
||||
|
||||
public static Character Spawn(string name, Vector2 worldPos)
|
||||
{
|
||||
Character spawnedCharacter = null;
|
||||
Vector2 spawnPosition = worldPos;
|
||||
|
||||
string characterLowerCase = name.ToLowerInvariant();
|
||||
JobPrefab job = null;
|
||||
if (!JobPrefab.Prefabs.ContainsKey(characterLowerCase))
|
||||
{
|
||||
job = JobPrefab.Prefabs.Find(jp => jp.Name != null && jp.Name.Equals(characterLowerCase, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
else
|
||||
{
|
||||
job = JobPrefab.Prefabs[characterLowerCase];
|
||||
}
|
||||
bool human = job != null || characterLowerCase == CharacterPrefab.HumanSpeciesName;
|
||||
|
||||
|
||||
if (string.IsNullOrWhiteSpace(name)) { return null; }
|
||||
|
||||
if (human)
|
||||
{
|
||||
var variant = job != null ? Rand.Range(0, job.Variants, Rand.RandSync.Server) : 0;
|
||||
CharacterInfo characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobPrefab: job, variant: variant);
|
||||
spawnedCharacter = Character.Create(characterInfo, spawnPosition, ToolBox.RandomSeed(8));
|
||||
if (GameMain.GameSession != null)
|
||||
{
|
||||
//TODO: a way to select which team to spawn to?
|
||||
spawnedCharacter.TeamID = Character.Controlled != null ? Character.Controlled.TeamID : CharacterTeamType.Team1;
|
||||
#if CLIENT
|
||||
GameMain.GameSession.CrewManager.AddCharacter(spawnedCharacter);
|
||||
#endif
|
||||
}
|
||||
spawnedCharacter.GiveJobItems(null);
|
||||
spawnedCharacter.Info.StartItemsGiven = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CharacterPrefab.FindBySpeciesName(name) != null)
|
||||
{
|
||||
spawnedCharacter = Character.Create(name, spawnPosition, ToolBox.RandomSeed(8));
|
||||
}
|
||||
}
|
||||
|
||||
return spawnedCharacter;
|
||||
}
|
||||
|
||||
public static string SpawnItem(string name, Vector2 pos, bool inventory = false, Character character = null)
|
||||
{
|
||||
string error;
|
||||
DebugConsole.SpawnItem(new string[] { name, inventory ? "inventory" : "cursor" }, pos, character, out error);
|
||||
return error;
|
||||
}
|
||||
|
||||
public static void RemoveItem(Item item)
|
||||
{
|
||||
EntitySpawner.Spawner.AddToRemoveQueue(item);
|
||||
}
|
||||
|
||||
public static ItemPrefab GetItemPrefab(string itemNameOrId)
|
||||
{
|
||||
ItemPrefab itemPrefab =
|
||||
(MapEntityPrefab.Find(itemNameOrId, identifier: null, showErrorMessages: false) ??
|
||||
MapEntityPrefab.Find(null, identifier: itemNameOrId, showErrorMessages: false)) as ItemPrefab;
|
||||
|
||||
return itemPrefab;
|
||||
}
|
||||
|
||||
public void AddItemPrefabToSpawnQueue(ItemPrefab itemPrefab, Vector2 position, DynValue spawned = null)
|
||||
{
|
||||
EntitySpawner.Spawner.AddToSpawnQueue(itemPrefab, position, onSpawned: (Item item) => {
|
||||
if (spawned?.Type == DataType.Function) GameMain.Lua.CallFunction(spawned, UserData.Create(item));
|
||||
});
|
||||
}
|
||||
|
||||
public void AddItemPrefabToSpawnQueue(ItemPrefab itemPrefab, Inventory inventory, DynValue spawned = null)
|
||||
{
|
||||
EntitySpawner.Spawner.AddToSpawnQueue(itemPrefab, inventory, onSpawned: (Item item) => {
|
||||
if (spawned?.Type == DataType.Function) GameMain.Lua.CallFunction(spawned, UserData.Create(item));
|
||||
});
|
||||
}
|
||||
|
||||
public static Submarine GetRespawnSub()
|
||||
{
|
||||
#if SERVER
|
||||
if (GameMain.Server.RespawnManager == null)
|
||||
return null;
|
||||
return GameMain.Server.RespawnManager.RespawnShuttle;
|
||||
#else
|
||||
if (GameMain.Client.RespawnManager == null)
|
||||
return null;
|
||||
return GameMain.Client.RespawnManager.RespawnShuttle;
|
||||
#endif
|
||||
}
|
||||
|
||||
public static Items.Components.Steering GetSubmarineSteering(Submarine sub)
|
||||
{
|
||||
foreach (Item item in Item.ItemList)
|
||||
{
|
||||
if (item.Submarine != sub) continue;
|
||||
|
||||
var steering = item.GetComponent<Items.Components.Steering>();
|
||||
if (steering != null)
|
||||
{
|
||||
return steering;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static WifiComponent GetWifiComponent(Item item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
return item.GetComponent<WifiComponent>();
|
||||
}
|
||||
|
||||
public static LightComponent GetLightComponent(Item item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
return item.GetComponent<LightComponent>();
|
||||
}
|
||||
|
||||
public static CustomInterface GetCustomInterface(Item item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
return item.GetComponent<CustomInterface>();
|
||||
}
|
||||
|
||||
public static Fabricator GetFabricatorComponent(Item item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
return item.GetComponent<Fabricator>();
|
||||
}
|
||||
|
||||
public static Holdable GetHoldableComponent(Item item)
|
||||
{
|
||||
if (item == null) return null;
|
||||
return item.GetComponent<Holdable>();
|
||||
}
|
||||
|
||||
public static void ExecuteCommand(string command)
|
||||
{
|
||||
DebugConsole.ExecuteCommand(command);
|
||||
}
|
||||
|
||||
public static Signal CreateSignal(string value, int stepsTaken = 1, Character sender = null, Item source = null, float power = 0, float strength = 1)
|
||||
{
|
||||
return new Signal(value, stepsTaken, sender, source, power, strength);
|
||||
}
|
||||
|
||||
public static ContentPackage[] GetEnabledContentPackages()
|
||||
{
|
||||
return GameMain.Config.AllEnabledPackages.ToArray();
|
||||
}
|
||||
|
||||
public static List<string> GetEnabledPackagesDirectlyFromFile()
|
||||
{
|
||||
List<string> enabledPackages = new List<string>();
|
||||
|
||||
XDocument doc = XMLExtensions.LoadXml("config_player.xml");
|
||||
var contentPackagesElement = doc.Root.Element("contentpackages");
|
||||
|
||||
string coreName = contentPackagesElement.Element("core")?.GetAttributeString("name", "");
|
||||
enabledPackages.Add(coreName);
|
||||
|
||||
XElement regularElement = contentPackagesElement.Element("regular");
|
||||
List<XElement> subElements = regularElement?.Elements()?.ToList();
|
||||
|
||||
foreach (var subElement in subElements)
|
||||
{
|
||||
if (!bool.TryParse(subElement.GetAttributeString("enabled", "false"), out bool enabled) || !enabled) { continue; }
|
||||
|
||||
string name = subElement.GetAttributeString("name", null);
|
||||
enabledPackages.Add(name);
|
||||
}
|
||||
return enabledPackages;
|
||||
}
|
||||
|
||||
private List<DebugConsole.Command> luaAddedCommand = new List<DebugConsole.Command>();
|
||||
|
||||
public void RemoveCommand(string name)
|
||||
{
|
||||
for (var i = 0; i < DebugConsole.Commands.Count; i++)
|
||||
{
|
||||
foreach (var cmdname in DebugConsole.Commands[i].names)
|
||||
{
|
||||
if (cmdname == name)
|
||||
{
|
||||
luaAddedCommand.Remove(DebugConsole.Commands[i]);
|
||||
DebugConsole.Commands.RemoveAt(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddCommand(string name, string help, object onExecute, object getValidArgs = null, bool isCheat = false)
|
||||
{
|
||||
var cmd = new DebugConsole.Command(name, help, (string[] arg1) => { GameMain.Lua.CallFunction(onExecute, new object[] { arg1 }); },
|
||||
() =>
|
||||
{
|
||||
if (getValidArgs == null) return null;
|
||||
var result = new LuaResult(GameMain.Lua.CallFunction(getValidArgs, new object[] { }));
|
||||
var obj = result.Object();
|
||||
if (obj is string[][]) return (string[][])obj;
|
||||
return null;
|
||||
}, isCheat);
|
||||
|
||||
luaAddedCommand.Add(cmd);
|
||||
DebugConsole.Commands.Add(cmd);
|
||||
|
||||
#if SERVER
|
||||
foreach (var client in GameMain.Server.ConnectedClients) {
|
||||
var index = client.PermittedConsoleCommands.FindIndex((pc) => pc.names[0] == cmd.names[0]);
|
||||
if (index > -1) {
|
||||
client.PermittedConsoleCommands[index] = cmd;
|
||||
}
|
||||
}
|
||||
foreach (var permissions in GameMain.Server.ServerSettings.ClientPermissions) {
|
||||
var index = permissions.PermittedCommands.FindIndex((pc) => pc.names[0] == cmd.names[0]);
|
||||
if (index > -1) {
|
||||
permissions.PermittedCommands[index] = cmd;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public List<DebugConsole.Command> Commands => DebugConsole.Commands;
|
||||
|
||||
public void AssignOnExecute(string names, object onExecute) => DebugConsole.AssignOnExecute(names, (string[] a) => { GameMain.Lua.CallFunction(onExecute, new object[] { a }); });
|
||||
|
||||
|
||||
#if SERVER
|
||||
|
||||
public static void SendMessage(string msg, ChatMessageType? messageType = null, Client sender = null, Character character = null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage(msg, messageType, sender, character);
|
||||
}
|
||||
|
||||
public static void SendMessage(string msg, int messageType, Client sender = null, Character character = null)
|
||||
{
|
||||
GameMain.Server.SendChatMessage(msg, (ChatMessageType)messageType, sender, character);
|
||||
}
|
||||
|
||||
public static void SendTraitorMessage(Client client, string msg, string missionid, TraitorMessageType type)
|
||||
{
|
||||
GameMain.Server.SendTraitorMessage(client, msg, missionid, type);
|
||||
}
|
||||
|
||||
public static void SendDirectChatMessage(string sendername, string text, Character sender, ChatMessageType messageType = ChatMessageType.Private, Client client = null, string iconStyle = "")
|
||||
{
|
||||
|
||||
ChatMessage cm = ChatMessage.Create(sendername, text, messageType, sender, client);
|
||||
cm.IconStyle = iconStyle;
|
||||
|
||||
GameMain.Server.SendDirectChatMessage(cm, client);
|
||||
|
||||
}
|
||||
|
||||
public static void SendDirectChatMessage(ChatMessage chatMessage, Client client)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(chatMessage, client);
|
||||
}
|
||||
|
||||
public static void Log(string message, ServerLog.MessageType type)
|
||||
{
|
||||
GameServer.Log(message, type);
|
||||
}
|
||||
|
||||
public static void DispatchRespawnSub()
|
||||
{
|
||||
GameMain.Server.RespawnManager.DispatchShuttle();
|
||||
}
|
||||
|
||||
public static void StartGame()
|
||||
{
|
||||
GameMain.Server.StartGame();
|
||||
}
|
||||
|
||||
public static void EndGame()
|
||||
{
|
||||
GameMain.Server.EndGame();
|
||||
}
|
||||
|
||||
public void AssignOnClientRequestExecute(string names, object onExecute) => DebugConsole.AssignOnClientRequestExecute(names, (Client a, Vector2 b, string[] c) => { GameMain.Lua.CallFunction(onExecute, new object[] { a, b, c }); });
|
||||
|
||||
#endif
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
mapEntityUpdateInterval = 1;
|
||||
gapUpdateInterval = 4;
|
||||
|
||||
foreach (var cmd in luaAddedCommand)
|
||||
{
|
||||
DebugConsole.Commands.Remove(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,320 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MoonSharp.Interpreter;
|
||||
using HarmonyLib;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class LuaHook
|
||||
{
|
||||
public LuaHook()
|
||||
{
|
||||
_hookPrefixMethods = new Dictionary<long, HashSet<object>>();
|
||||
_hookPostfixMethods = new Dictionary<long, HashSet<object>>();
|
||||
}
|
||||
|
||||
public class HookFunction
|
||||
{
|
||||
public string name;
|
||||
public string hookName;
|
||||
public object function;
|
||||
|
||||
public HookFunction(string n, string hn, object func)
|
||||
{
|
||||
name = n;
|
||||
hookName = hn;
|
||||
function = func;
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, Dictionary<string, HookFunction>> hookFunctions = new Dictionary<string, Dictionary<string, HookFunction>>();
|
||||
|
||||
private static Dictionary<long, HashSet<object>> _hookPrefixMethods;
|
||||
private static Dictionary<long, HashSet<object>> _hookPostfixMethods;
|
||||
|
||||
private Queue<Tuple<float, object, object[]>> queuedFunctionCalls = new Queue<Tuple<float, object, object[]>>();
|
||||
|
||||
public enum HookMethodType
|
||||
{
|
||||
Before, After
|
||||
}
|
||||
|
||||
static void _hookLuaPatch(MethodBase __originalMethod, object[] __args, object __instance, out LuaResult result, HookMethodType hookMethodType)
|
||||
{
|
||||
result = new LuaResult(null);
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession?.IsRunning == false && GameMain.IsSingleplayer)
|
||||
return;
|
||||
#endif
|
||||
|
||||
try
|
||||
{
|
||||
var @params = __originalMethod.GetParameters();
|
||||
var ptable = new Dictionary<string, object>();
|
||||
for (int i = 0; i < @params.Length; i++)
|
||||
{
|
||||
ptable.Add(@params[i].Name, __args[i]);
|
||||
}
|
||||
|
||||
var funcAddr = ((long)__originalMethod.MethodHandle.GetFunctionPointer());
|
||||
HashSet<object> methodSet = null;
|
||||
switch (hookMethodType)
|
||||
{
|
||||
case HookMethodType.Before:
|
||||
methodSet = _hookPrefixMethods[funcAddr];
|
||||
break;
|
||||
case HookMethodType.After:
|
||||
methodSet = _hookPostfixMethods[funcAddr];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (methodSet != null)
|
||||
{
|
||||
foreach (var hookMethod in methodSet)
|
||||
{
|
||||
result = new LuaResult(GameMain.Lua.lua.Call(hookMethod, __instance, ptable));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(ex, nameof(_hookLuaPatch));
|
||||
}
|
||||
}
|
||||
|
||||
static bool HookLuaPatchPrefix(MethodBase __originalMethod, object[] __args, object __instance)
|
||||
{
|
||||
_hookLuaPatch(__originalMethod, __args, __instance, out LuaResult result, HookMethodType.Before);
|
||||
|
||||
return result.IsNull();
|
||||
}
|
||||
|
||||
static bool HookLuaPatchRetPrefix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance)
|
||||
{
|
||||
_hookLuaPatch(__originalMethod, __args, __instance, out LuaResult result, HookMethodType.Before);
|
||||
|
||||
if (!result.IsNull())
|
||||
{
|
||||
__result = result.Object();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void HookLuaPatchPostfix(MethodBase __originalMethod, object[] __args, object __instance)
|
||||
{
|
||||
_hookLuaPatch(__originalMethod, __args, __instance, out LuaResult result, HookMethodType.After);
|
||||
}
|
||||
|
||||
static void HookLuaPatchRetPostfix(MethodBase __originalMethod, object[] __args, ref object __result, object __instance)
|
||||
{
|
||||
_hookLuaPatch(__originalMethod, __args, __instance, out LuaResult result, HookMethodType.After);
|
||||
|
||||
if (!result.IsNull())
|
||||
__result = result.Object();
|
||||
}
|
||||
|
||||
private const BindingFlags DefaultBindingFlags = BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
|
||||
private static MethodInfo _miHookLuaPatchPrefix = typeof(LuaHook).GetMethod("HookLuaPatchPrefix", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
private static MethodInfo _miHookLuaPatchRetPrefix = typeof(LuaHook).GetMethod("HookLuaPatchRetPrefix", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
private static MethodInfo _miHookLuaPatchPostfix = typeof(LuaHook).GetMethod("HookLuaPatchPostfix", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
private static MethodInfo _miHookLuaPatchRetPostfix = typeof(LuaHook).GetMethod("HookLuaPatchRetPostfix", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
public void HookMethod(string className, string methodName, string[] parameterNames, object hookMethod, HookMethodType hookMethodType = HookMethodType.Before)
|
||||
{
|
||||
if (hookMethod == null)
|
||||
{
|
||||
GameMain.Lua.PrintError("hookMethod cannot be null");
|
||||
return;
|
||||
}
|
||||
|
||||
var classType = Type.GetType(className);
|
||||
MethodInfo methodInfo = null;
|
||||
|
||||
if (parameterNames != null)
|
||||
{
|
||||
Type[] parameterTypes = parameterNames.Select(x => AccessTools.TypeByName(x)).ToArray();
|
||||
methodInfo = classType.GetMethod(methodName, DefaultBindingFlags, null, parameterTypes, null);
|
||||
}
|
||||
else
|
||||
{
|
||||
methodInfo = classType.GetMethod(methodName, DefaultBindingFlags);
|
||||
}
|
||||
|
||||
if (methodInfo == null)
|
||||
{
|
||||
GameMain.Lua.PrintError($"can't find method({className}.{methodName}) with these parameters' types({string.Join(", ", parameterNames)})");
|
||||
return;
|
||||
}
|
||||
|
||||
var funcAddr = ((long)methodInfo.MethodHandle.GetFunctionPointer());
|
||||
var patches = Harmony.GetPatchInfo(methodInfo);
|
||||
|
||||
if (hookMethodType == HookMethodType.Before)
|
||||
{
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
{
|
||||
if (patches == null || patches.Prefixes == null || patches.Prefixes.Find(patch => patch.PatchMethod == _miHookLuaPatchPrefix) == null)
|
||||
{
|
||||
GameMain.Lua.harmony.Patch(methodInfo, prefix: new HarmonyMethod(_miHookLuaPatchPrefix));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (patches == null || patches.Prefixes == null || patches.Prefixes.Find(patch => patch.PatchMethod == _miHookLuaPatchRetPrefix) == null)
|
||||
{
|
||||
GameMain.Lua.harmony.Patch(methodInfo, prefix: new HarmonyMethod(_miHookLuaPatchRetPrefix));
|
||||
}
|
||||
}
|
||||
|
||||
if (_hookPrefixMethods.TryGetValue(funcAddr, out HashSet<object> methodSet))
|
||||
{
|
||||
methodSet.Add(hookMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
_hookPrefixMethods.Add(funcAddr, new HashSet<object>() { hookMethod });
|
||||
}
|
||||
|
||||
}
|
||||
else if (hookMethodType == HookMethodType.After)
|
||||
{
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
{
|
||||
if (patches == null || patches.Postfixes == null || patches.Postfixes.Find(patch => patch.PatchMethod == _miHookLuaPatchPostfix) == null)
|
||||
{
|
||||
GameMain.Lua.harmony.Patch(methodInfo, postfix: new HarmonyMethod(_miHookLuaPatchPostfix));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (patches == null || patches.Postfixes == null || patches.Postfixes.Find(patch => patch.PatchMethod == _miHookLuaPatchRetPostfix) == null)
|
||||
{
|
||||
GameMain.Lua.harmony.Patch(methodInfo, postfix: new HarmonyMethod(_miHookLuaPatchRetPostfix));
|
||||
}
|
||||
}
|
||||
|
||||
if (_hookPostfixMethods.TryGetValue(funcAddr, out HashSet<object> methodSet))
|
||||
{
|
||||
methodSet.Add(hookMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
_hookPostfixMethods.Add(funcAddr, new HashSet<object>() { hookMethod });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void HookMethod(string className, string methodName, object hookMethod, HookMethodType hookMethodType = HookMethodType.Before)
|
||||
{
|
||||
HookMethod(className, methodName, null, hookMethod, hookMethodType);
|
||||
}
|
||||
|
||||
|
||||
public void EnqueueFunction(object function, params object[] args)
|
||||
{
|
||||
queuedFunctionCalls.Enqueue(new Tuple<float, object, object[]>(0, function, args));
|
||||
}
|
||||
|
||||
public void EnqueueTimedFunction(float time, object function, params object[] args)
|
||||
{
|
||||
queuedFunctionCalls.Enqueue(new Tuple<float, object, object[]>(time, function, args));
|
||||
}
|
||||
|
||||
public void Add(string name, string hookName, object function)
|
||||
{
|
||||
if (name == null && hookName == null && function == null) return;
|
||||
|
||||
name = name.ToLower();
|
||||
|
||||
if (!hookFunctions.ContainsKey(name))
|
||||
hookFunctions.Add(name, new Dictionary<string, HookFunction>());
|
||||
|
||||
hookFunctions[name][hookName] = new HookFunction(name, hookName, function);
|
||||
}
|
||||
|
||||
public void Remove(string name, string hookName)
|
||||
{
|
||||
if (name == null && hookName == null) return;
|
||||
|
||||
name = name.ToLower();
|
||||
|
||||
if (!hookFunctions.ContainsKey(name))
|
||||
return;
|
||||
|
||||
if (hookFunctions[name].ContainsKey(hookName))
|
||||
hookFunctions[name].Remove(hookName);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (queuedFunctionCalls.TryPeek(out Tuple<float, object, object[]> result))
|
||||
{
|
||||
if (Timing.TotalTime >= result.Item1)
|
||||
{
|
||||
GameMain.Lua.CallFunction(result.Item2, result.Item3);
|
||||
|
||||
queuedFunctionCalls.Dequeue();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(ex, $"queuedFunctionCalls was {queuedFunctionCalls}");
|
||||
}
|
||||
}
|
||||
|
||||
public object Call(string name, params object[] args)
|
||||
{
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession?.IsRunning == false && GameMain.IsSingleplayer)
|
||||
return null;
|
||||
#endif
|
||||
if (GameMain.Lua == null) return null;
|
||||
if (name == null) return null;
|
||||
if (args == null) { args = new object[] { }; }
|
||||
|
||||
name = name.ToLower();
|
||||
|
||||
if (!hookFunctions.ContainsKey(name))
|
||||
return null;
|
||||
|
||||
object lastResult = null;
|
||||
|
||||
foreach (HookFunction hf in hookFunctions[name].Values)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hf.function is Closure)
|
||||
{
|
||||
var result = GameMain.Lua.lua.Call(hf.function, args);
|
||||
if (!result.IsNil())
|
||||
lastResult = result;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
StringBuilder argsSb = new StringBuilder();
|
||||
foreach (var arg in args)
|
||||
{
|
||||
argsSb.Append(arg + " ");
|
||||
}
|
||||
|
||||
GameMain.Lua.HandleLuaException(e, $"Error in Hook '{name}'->'{hf.hookName}', with args '{argsSb}'");
|
||||
}
|
||||
}
|
||||
|
||||
return lastResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using MoonSharp.Interpreter;
|
||||
using MoonSharp.Interpreter.Interop;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class LuaUserData
|
||||
{
|
||||
public static Type GetType(string typeName)
|
||||
{
|
||||
var type = Type.GetType(typeName);
|
||||
if (type != null) return type;
|
||||
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
type = a.GetType(typeName);
|
||||
if (type != null)
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static IUserDataDescriptor RegisterType(string typeName)
|
||||
{
|
||||
Type type = GetType(typeName);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to register a type that doesn't exist: {typeName}."));
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.RegisterType), new Type[2] { typeof(InteropAccessMode), typeof(string) });
|
||||
MethodInfo generic = method.MakeGenericMethod(type);
|
||||
return (IUserDataDescriptor)generic.Invoke(null, new object[] { null, null });
|
||||
}
|
||||
|
||||
public static void UnregisterType(string typeName)
|
||||
{
|
||||
Type type = GetType(typeName);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to unregister a type that doesn't exist: {typeName}."));
|
||||
return;
|
||||
}
|
||||
|
||||
MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.UnregisterType), new Type[2] { typeof(InteropAccessMode), typeof(string) });
|
||||
MethodInfo generic = method.MakeGenericMethod(type);
|
||||
generic.Invoke(null, new object[] { null, null });
|
||||
}
|
||||
public static IUserDataDescriptor RegisterGenericType(string typeName, params string[] typeNameArguements)
|
||||
{
|
||||
Type type = GetType(typeName);
|
||||
Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray();
|
||||
Type genericType = type.MakeGenericType(typeArguements);
|
||||
return UserData.RegisterType(genericType);
|
||||
}
|
||||
|
||||
public static void UnregisterGenericType(string typeName, params string[] typeNameArguements)
|
||||
{
|
||||
Type type = GetType(typeName);
|
||||
Type[] typeArguements = typeNameArguements.Select(x => GetType(x)).ToArray();
|
||||
Type genericType = type.MakeGenericType(typeArguements);
|
||||
UserData.UnregisterType(genericType);
|
||||
}
|
||||
|
||||
private static bool IsType<T>(object obj) { return obj is T; }
|
||||
|
||||
public static bool IsTargetType(object obj, string typeName)
|
||||
{
|
||||
var type = GetType(typeName);
|
||||
MethodInfo method = typeof(LuaUserData).GetMethod(nameof(IsType), BindingFlags.NonPublic | BindingFlags.Static);
|
||||
MethodInfo generic = method.MakeGenericMethod(type);
|
||||
return (bool)generic.Invoke(null, new object[] { obj });
|
||||
}
|
||||
|
||||
public static object CreateStatic(string typeName)
|
||||
{
|
||||
Type type = GetType(typeName);
|
||||
|
||||
if (type == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to create a static userdata of a type that doesn't exist: {typeName}."));
|
||||
return null;
|
||||
}
|
||||
|
||||
MethodInfo method = typeof(UserData).GetMethod(nameof(UserData.CreateStatic), 1, new Type[0]);
|
||||
MethodInfo generic = method.MakeGenericMethod(type);
|
||||
return generic.Invoke(null, null);
|
||||
}
|
||||
|
||||
public static void MakeFieldAccessible(IUserDataDescriptor IUUD, string fieldName)
|
||||
{
|
||||
if (IUUD == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to use a UserDataDescriptor that is null to make {fieldName} accessible."));
|
||||
return;
|
||||
}
|
||||
|
||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
||||
var field = IUUD.Type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
||||
|
||||
if (field == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to make field '{fieldName}' accessible, but the field doesn't exist."));
|
||||
return;
|
||||
}
|
||||
|
||||
descriptor.RemoveMember(fieldName);
|
||||
descriptor.AddMember(fieldName, new FieldMemberDescriptor(field, InteropAccessMode.Default));
|
||||
}
|
||||
|
||||
public static void MakeMethodAccessible(IUserDataDescriptor IUUD, string methodName)
|
||||
{
|
||||
if (IUUD == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to use a UserDataDescriptor that is null to make {methodName} accessible."));
|
||||
return;
|
||||
}
|
||||
|
||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
||||
var method = IUUD.Type.GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
|
||||
|
||||
if (method == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to make method '{method}' accessible, but the method doesn't exist."));
|
||||
return;
|
||||
}
|
||||
|
||||
descriptor.RemoveMember(methodName);
|
||||
descriptor.AddMember(methodName, new MethodMemberDescriptor(method, InteropAccessMode.Default));
|
||||
}
|
||||
|
||||
public static void AddMethod(IUserDataDescriptor IUUD, string methodName, object function)
|
||||
{
|
||||
if (IUUD == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to use a UserDataDescriptor that is null to add method {methodName}."));
|
||||
return;
|
||||
}
|
||||
|
||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
||||
descriptor.RemoveMember(methodName);
|
||||
descriptor.AddMember(methodName, new ObjectCallbackMemberDescriptor(methodName, (object arg1, ScriptExecutionContext arg2, CallbackArguments arg3) =>
|
||||
{
|
||||
if (GameMain.Lua != null)
|
||||
return GameMain.Lua.CallFunction(function, arg3.GetArray());
|
||||
return null;
|
||||
}));
|
||||
}
|
||||
|
||||
public static void RemoveMember(IUserDataDescriptor IUUD, string memberName)
|
||||
{
|
||||
if (IUUD == null)
|
||||
{
|
||||
GameMain.Lua.HandleLuaException(new Exception($"Tried to use a UserDataDescriptor that is null to remove the member {memberName}."));
|
||||
return;
|
||||
}
|
||||
|
||||
var descriptor = (StandardUserDataDescriptor)IUUD;
|
||||
descriptor.RemoveMember(memberName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,9 +230,9 @@ namespace Barotrauma
|
||||
game.Stop();
|
||||
hook.Call("stop", new object[] { });
|
||||
|
||||
hook = new LuaHook(null);
|
||||
game = new LuaGame(null);
|
||||
networking = new LuaNetworking(null);
|
||||
hook = null;
|
||||
game = null;
|
||||
networking = null;
|
||||
luaScriptLoader = null;
|
||||
|
||||
luaSetup = null;
|
||||
@@ -259,13 +259,12 @@ namespace Barotrauma
|
||||
harmony = new Harmony("com.LuaForBarotrauma");
|
||||
harmony.UnpatchAll();
|
||||
|
||||
hook = new LuaHook(this);
|
||||
game = new LuaGame(this);
|
||||
networking = new LuaNetworking(this);
|
||||
hook = new LuaHook();
|
||||
game = new LuaGame();
|
||||
networking = new LuaNetworking();
|
||||
|
||||
UserData.RegisterType<LuaHook>();
|
||||
UserData.RegisterType<LuaGame>();
|
||||
UserData.RegisterType<LuaRandom>();
|
||||
UserData.RegisterType<LuaTimer>();
|
||||
UserData.RegisterType<LuaFile>();
|
||||
UserData.RegisterType<LuaNetworking>();
|
||||
@@ -288,8 +287,7 @@ namespace Barotrauma
|
||||
lua.Globals["LuaUserData"] = UserData.CreateStatic<LuaUserData>();
|
||||
lua.Globals["Game"] = game;
|
||||
lua.Globals["Hook"] = hook;
|
||||
lua.Globals["Random"] = new LuaRandom();
|
||||
lua.Globals["Timer"] = new LuaTimer(this);
|
||||
lua.Globals["Timer"] = new LuaTimer();
|
||||
lua.Globals["File"] = UserData.CreateStatic<LuaFile>();
|
||||
lua.Globals["Networking"] = networking;
|
||||
|
||||
@@ -316,9 +314,9 @@ namespace Barotrauma
|
||||
|
||||
public LuaSetup()
|
||||
{
|
||||
hook = new LuaHook(null);
|
||||
game = new LuaGame(null);
|
||||
networking = new LuaNetworking(null);
|
||||
hook = new LuaHook();
|
||||
game = new LuaGame();
|
||||
networking = new LuaNetworking();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user