mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 06:19:22 +00:00
further cleanup of repo
This commit is contained in:
parent
4f8dcb0cd0
commit
323eb92f2e
140 changed files with 1 additions and 2430 deletions
|
@ -0,0 +1,41 @@
|
|||
using MoonSharp.Interpreter;
|
||||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.Savior;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
public struct LuaEventContext
|
||||
{
|
||||
private string SenderId { get; set; }
|
||||
public string SenderName { get; private set; }
|
||||
private DateTime LastInvokeTime { get; set; }
|
||||
private double TimeSinceLastInvoke { get; set; }
|
||||
private bool IsLocal { get; set; }
|
||||
|
||||
public static LuaEventContext Create(string senderId, DateTime lastInvokeTime)
|
||||
{
|
||||
var playerName = CVRPlayerManager.Instance.TryGetPlayerName(senderId);
|
||||
|
||||
return new LuaEventContext
|
||||
{
|
||||
SenderId = senderId,
|
||||
SenderName = playerName ?? "Unknown",
|
||||
LastInvokeTime = lastInvokeTime,
|
||||
TimeSinceLastInvoke = (DateTime.Now - lastInvokeTime).TotalSeconds,
|
||||
IsLocal = senderId == MetaPort.Instance.ownerId
|
||||
};
|
||||
}
|
||||
|
||||
public Table ToLuaTable(Script script)
|
||||
{
|
||||
Table table = new(script)
|
||||
{
|
||||
["senderId"] = SenderId,
|
||||
["senderName"] = SenderName,
|
||||
["lastInvokeTime"] = LastInvokeTime.ToUniversalTime().ToString("O"),
|
||||
["timeSinceLastInvoke"] = TimeSinceLastInvoke,
|
||||
["isLocal"] = IsLocal
|
||||
};
|
||||
return table;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
namespace NAK.LuaNetVars;
|
||||
|
||||
internal class LuaEventTracker
|
||||
{
|
||||
private class EventMetadata
|
||||
{
|
||||
public DateTime LastInvokeTime { get; set; }
|
||||
public Dictionary<string, DateTime> LastInvokeTimePerSender { get; } = new();
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, EventMetadata> _eventMetadata = new();
|
||||
|
||||
public DateTime GetLastInvokeTime(string eventName)
|
||||
{
|
||||
if (!_eventMetadata.TryGetValue(eventName, out var metadata))
|
||||
{
|
||||
metadata = new EventMetadata();
|
||||
_eventMetadata[eventName] = metadata;
|
||||
}
|
||||
return metadata.LastInvokeTime;
|
||||
}
|
||||
|
||||
public DateTime GetLastInvokeTimeForSender(string eventName, string senderId)
|
||||
{
|
||||
if (!_eventMetadata.TryGetValue(eventName, out var metadata))
|
||||
{
|
||||
metadata = new EventMetadata();
|
||||
_eventMetadata[eventName] = metadata;
|
||||
}
|
||||
|
||||
if (!metadata.LastInvokeTimePerSender.TryGetValue(senderId, out DateTime time))
|
||||
{
|
||||
return DateTime.MinValue;
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
public void UpdateInvokeTime(string eventName, string senderId)
|
||||
{
|
||||
if (!_eventMetadata.TryGetValue(eventName, out EventMetadata metadata))
|
||||
{
|
||||
metadata = new EventMetadata();
|
||||
_eventMetadata[eventName] = metadata;
|
||||
}
|
||||
|
||||
DateTime now = DateTime.Now;
|
||||
metadata.LastInvokeTime = now;
|
||||
metadata.LastInvokeTimePerSender[senderId] = now;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_eventMetadata.Clear();
|
||||
}
|
||||
|
||||
public void ClearEvent(string eventName)
|
||||
{
|
||||
_eventMetadata.Remove(eventName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Core.Util;
|
||||
using ABI_RC.Systems.ModNetwork;
|
||||
using ABI.CCK.Components;
|
||||
using ABI.Scripting.CVRSTL.Common;
|
||||
using MoonSharp.Interpreter;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
public partial class LuaNetVarController : MonoBehaviour
|
||||
{
|
||||
private static readonly HashSet<int> _hashes = new();
|
||||
|
||||
private const string MODULE_ID = "NAK.LNV:";
|
||||
|
||||
private int _uniquePathHash;
|
||||
private string ModNetworkID { get; set; }
|
||||
private CVRLuaClientBehaviour _luaClientBehaviour;
|
||||
|
||||
private readonly Dictionary<string, DynValue> _registeredNetworkVars = new();
|
||||
private readonly Dictionary<string, DynValue> _registeredNotifyCallbacks = new();
|
||||
private readonly Dictionary<string, DynValue> _registeredEventCallbacks = new();
|
||||
private readonly HashSet<string> _dirtyVariables = new();
|
||||
|
||||
private bool _requestInitialSync;
|
||||
private CVRSpawnable _spawnable;
|
||||
private CVRObjectSync _objectSync;
|
||||
|
||||
#region Unity Events
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (!Initialize())
|
||||
return;
|
||||
|
||||
// TODO: a manager script should be in charge of this
|
||||
// TODO: disabling object will kill coroutine
|
||||
StartCoroutine(SendVariableUpdatesCoroutine());
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
=> Cleanup();
|
||||
|
||||
#endregion Unity Events
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private bool Initialize()
|
||||
{
|
||||
if (!TryGetComponent(out _luaClientBehaviour)) return false;
|
||||
if (!TryGetUniqueNetworkID(out _uniquePathHash)) return false;
|
||||
|
||||
ModNetworkID = MODULE_ID + _uniquePathHash.ToString("X8");
|
||||
|
||||
if (ModNetworkID.Length > ModNetworkManager.MaxMessageIdLength)
|
||||
{
|
||||
LuaNetVarsMod.Logger.Error($"ModNetworkID ({ModNetworkID}) exceeds max length of {ModNetworkManager.MaxMessageIdLength} characters!");
|
||||
return false;
|
||||
}
|
||||
|
||||
_hashes.Add(_uniquePathHash);
|
||||
ModNetworkManager.Subscribe(ModNetworkID, OnMessageReceived);
|
||||
LuaNetVarsMod.Logger.Msg($"Registered LuaNetVarController with ModNetworkID: {ModNetworkID}");
|
||||
|
||||
switch (_luaClientBehaviour.Context.objContext)
|
||||
{
|
||||
case CVRLuaObjectContext.AVATAR:
|
||||
_requestInitialSync = !_luaClientBehaviour.Context.IsWornByMe;
|
||||
break;
|
||||
case CVRLuaObjectContext.PROP:
|
||||
_spawnable = _luaClientBehaviour.Context.RootComponent as CVRSpawnable;
|
||||
_requestInitialSync = !_luaClientBehaviour.Context.IsSpawnedByMe;
|
||||
break;
|
||||
case CVRLuaObjectContext.WORLD:
|
||||
_objectSync = GetComponentInParent<CVRObjectSync>();
|
||||
_requestInitialSync = true; // idk probably works
|
||||
break;
|
||||
default:
|
||||
_requestInitialSync = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: evaluate if having dedicated globals is better behaviour (i think so)
|
||||
// private void ConfigureLuaEnvironment()
|
||||
// {
|
||||
// _luaClientBehaviour.script.Globals["SendLuaEvent"] = DynValue.NewCallback(SendLuaEventCallback);
|
||||
// }
|
||||
|
||||
private void Cleanup()
|
||||
{
|
||||
_eventTracker.Clear();
|
||||
|
||||
if (_uniquePathHash == 0 || string.IsNullOrEmpty(ModNetworkID))
|
||||
return;
|
||||
|
||||
ModNetworkManager.Unsubscribe(ModNetworkID);
|
||||
LuaNetVarsMod.Logger.Msg($"Unsubscribed LuaNetVarController with ModNetworkID: {ModNetworkID}");
|
||||
_hashes.Remove(_uniquePathHash);
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator SendVariableUpdatesCoroutine()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
if (IsSyncOwner()) SendVariableUpdates();
|
||||
if (!_requestInitialSync) continue;
|
||||
_requestInitialSync = false;
|
||||
RequestVariableSync();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
|
||||
#region Ownership Methods
|
||||
|
||||
public bool IsSyncOwner()
|
||||
{
|
||||
if (_objectSync) return _objectSync.SyncedByMe; // idk
|
||||
if (_spawnable)
|
||||
{
|
||||
if (_spawnable.IsSyncedByMe()) return true; // is held / attached locally
|
||||
CVRSyncHelper.PropData propData = CVRSyncHelper.Props.Find(x => x.InstanceId == _spawnable.instanceId);
|
||||
if (propData != null) return propData.syncedBy == MetaPort.Instance.ownerId; // last updated by me
|
||||
return false; // not held / attached locally and not last updated by me
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public string GetSyncOwner()
|
||||
{
|
||||
if (_objectSync) return _objectSync.syncedBy;
|
||||
if (_spawnable)
|
||||
{
|
||||
CVRSyncHelper.PropData propData = CVRSyncHelper.Props.Find(x => x.InstanceId == _spawnable.instanceId);
|
||||
return propData?.syncedBy ?? string.Empty;
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
#endregion Ownership Methods
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.ModNetwork;
|
||||
using MoonSharp.Interpreter;
|
||||
using Unity.Services.Authentication.Internal;
|
||||
|
||||
namespace NAK.LuaNetVars
|
||||
{
|
||||
public partial class LuaNetVarController
|
||||
{
|
||||
private enum MessageType : byte
|
||||
{
|
||||
LuaVariable = 0,
|
||||
LuaEvent = 1,
|
||||
SyncVariables = 2,
|
||||
RequestSync = 3
|
||||
}
|
||||
|
||||
private readonly LuaEventTracker _eventTracker = new();
|
||||
|
||||
#region Mod Network Events
|
||||
|
||||
private void OnMessageReceived(ModNetworkMessage msg)
|
||||
{
|
||||
msg.Read(out byte msgTypeRaw);
|
||||
if (!Enum.IsDefined(typeof(MessageType), msgTypeRaw)) return;
|
||||
|
||||
MessageType msgType = (MessageType)msgTypeRaw;
|
||||
switch (msgType)
|
||||
{
|
||||
case MessageType.LuaVariable:
|
||||
HandleLuaVariableUpdate(msg);
|
||||
break;
|
||||
case MessageType.LuaEvent:
|
||||
HandleLuaEvent(msg);
|
||||
break;
|
||||
case MessageType.SyncVariables:
|
||||
HandleSyncVariables(msg);
|
||||
break;
|
||||
case MessageType.RequestSync:
|
||||
HandleRequestSyncVariables(msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLuaVariableUpdate(ModNetworkMessage msg)
|
||||
{
|
||||
msg.Read(out string varName);
|
||||
DynValue newValue = DeserializeDynValue(msg);
|
||||
|
||||
LuaNetVarsMod.Logger.Msg($"Received LuaVariable update: {varName} = {newValue}");
|
||||
|
||||
if (_registeredNetworkVars.TryGetValue(varName, out DynValue var))
|
||||
{
|
||||
UpdateNetworkVariable(varName, var, newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaNetVarsMod.Logger.Warning($"Received update for unregistered variable {varName}");
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleLuaEvent(ModNetworkMessage msg)
|
||||
{
|
||||
string senderId = msg.Sender;
|
||||
msg.Read(out string eventName);
|
||||
msg.Read(out int argsCount);
|
||||
|
||||
DateTime lastInvokeTime = _eventTracker.GetLastInvokeTimeForSender(eventName, senderId);
|
||||
LuaEventContext context = LuaEventContext.Create(senderId, lastInvokeTime);
|
||||
|
||||
// Update tracking
|
||||
_eventTracker.UpdateInvokeTime(eventName, senderId);
|
||||
|
||||
// Read event arguments
|
||||
var args = new DynValue[argsCount + 1]; // +1 for context
|
||||
args[0] = DynValue.FromObject(_luaClientBehaviour.script, context.ToLuaTable(_luaClientBehaviour.script));
|
||||
|
||||
for (int i = 0; i < argsCount; i++)
|
||||
{
|
||||
args[i + 1] = DeserializeDynValue(msg);
|
||||
}
|
||||
|
||||
LuaNetVarsMod.Logger.Msg($"Received LuaEvent: {eventName} from {context.SenderName} with {argsCount} args");
|
||||
|
||||
InvokeLuaEvent(eventName, args);
|
||||
}
|
||||
|
||||
private void HandleSyncVariables(ModNetworkMessage msg)
|
||||
{
|
||||
msg.Read(out int varCount);
|
||||
for (int i = 0; i < varCount; i++)
|
||||
{
|
||||
msg.Read(out string varName);
|
||||
DynValue newValue = DeserializeDynValue(msg);
|
||||
|
||||
if (_registeredNetworkVars.TryGetValue(varName, out DynValue var))
|
||||
{
|
||||
UpdateNetworkVariable(varName, var, newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaNetVarsMod.Logger.Warning($"Received sync for unregistered variable {varName}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleRequestSyncVariables(ModNetworkMessage msg)
|
||||
{
|
||||
if (!IsSyncOwner()) return;
|
||||
SendVariableSyncToUser(msg.Sender);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Event Invocation
|
||||
|
||||
private void InvokeLuaEvent(string eventName, DynValue[] args)
|
||||
{
|
||||
if (_registeredEventCallbacks.TryGetValue(eventName, out DynValue callback))
|
||||
{
|
||||
_luaClientBehaviour.script.Call(callback, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
LuaNetVarsMod.Logger.Warning($"No registered callback for event {eventName}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Sending Methods
|
||||
|
||||
private void SendVariableUpdates()
|
||||
{
|
||||
if (_dirtyVariables.Count == 0) return;
|
||||
|
||||
using ModNetworkMessage modMsg = new(ModNetworkID); // can pass target userids as params if needed
|
||||
modMsg.Write((byte)MessageType.SyncVariables);
|
||||
modMsg.Write(_dirtyVariables.Count);
|
||||
modMsg.Send();
|
||||
|
||||
foreach (var varName in _dirtyVariables)
|
||||
{
|
||||
modMsg.Write(varName);
|
||||
SerializeDynValue(modMsg, _registeredNetworkVars[varName]);
|
||||
}
|
||||
|
||||
_dirtyVariables.Clear();
|
||||
}
|
||||
|
||||
private void SendVariableSyncToUser(string userId)
|
||||
{
|
||||
using ModNetworkMessage modMsg = new(ModNetworkID, userId);
|
||||
modMsg.Write((byte)MessageType.SyncVariables);
|
||||
modMsg.Write(_registeredNetworkVars.Count);
|
||||
foreach (var kvp in _registeredNetworkVars)
|
||||
{
|
||||
modMsg.Write(kvp.Key);
|
||||
SerializeDynValue(modMsg, kvp.Value);
|
||||
}
|
||||
modMsg.Send();
|
||||
|
||||
LuaNetVarsMod.Logger.Msg($"Sent variable sync to {userId}");
|
||||
}
|
||||
|
||||
private void RequestVariableSync()
|
||||
{
|
||||
using ModNetworkMessage modMsg = new(ModNetworkID);
|
||||
modMsg.Write((byte)MessageType.RequestSync);
|
||||
modMsg.Send();
|
||||
LuaNetVarsMod.Logger.Msg("Requested variable sync");
|
||||
}
|
||||
|
||||
// private DynValue SendLuaEventCallback(ScriptExecutionContext context, CallbackArguments args)
|
||||
// {
|
||||
// if (args.Count < 1) return DynValue.Nil;
|
||||
//
|
||||
// var eventName = args[0].CastToString();
|
||||
// var eventArgs = args.GetArray().Skip(1).ToArray();
|
||||
//
|
||||
// SendLuaEvent(eventName, eventArgs);
|
||||
//
|
||||
// return DynValue.Nil;
|
||||
// }
|
||||
|
||||
internal void SendLuaEvent(string eventName, DynValue[] args)
|
||||
{
|
||||
string senderId = MetaPort.Instance.ownerId;
|
||||
DateTime lastInvokeTime = _eventTracker.GetLastInvokeTimeForSender(eventName, senderId);
|
||||
LuaEventContext context = LuaEventContext.Create(senderId, lastInvokeTime);
|
||||
|
||||
// Update tracking
|
||||
_eventTracker.UpdateInvokeTime(eventName, senderId);
|
||||
|
||||
var argsWithContext = new DynValue[args.Length + 1];
|
||||
argsWithContext[0] = DynValue.FromObject(_luaClientBehaviour.script, context.ToLuaTable(_luaClientBehaviour.script));
|
||||
Array.Copy(args, 0, argsWithContext, 1, args.Length);
|
||||
|
||||
InvokeLuaEvent(eventName, argsWithContext);
|
||||
|
||||
using ModNetworkMessage modMsg = new(ModNetworkID);
|
||||
modMsg.Write((byte)MessageType.LuaEvent);
|
||||
modMsg.Write(eventName);
|
||||
modMsg.Write(args.Length);
|
||||
|
||||
foreach (DynValue arg in args)
|
||||
SerializeDynValue(modMsg, arg);
|
||||
|
||||
modMsg.Send();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
public partial class LuaNetVarController
|
||||
{
|
||||
internal void RegisterNetworkVar(string varName)
|
||||
{
|
||||
if (_registeredNetworkVars.ContainsKey(varName))
|
||||
{
|
||||
LuaNetVarsMod.Logger.Warning($"Network variable {varName} already registered!");
|
||||
return;
|
||||
}
|
||||
|
||||
_registeredNetworkVars[varName] = DynValue.Nil;
|
||||
_luaClientBehaviour.script.Globals[varName] = DynValue.Nil;
|
||||
|
||||
RegisterGetterFunction(varName);
|
||||
RegisterSetterFunction(varName);
|
||||
|
||||
LuaNetVarsMod.Logger.Msg($"Registered network variable {varName}");
|
||||
}
|
||||
|
||||
private void RegisterGetterFunction(string varName)
|
||||
{
|
||||
_luaClientBehaviour.script.Globals["Get" + varName] = DynValue.NewCallback((context, args) =>
|
||||
{
|
||||
return _registeredNetworkVars.TryGetValue(varName, out var value) ? value : DynValue.Nil;
|
||||
});
|
||||
}
|
||||
|
||||
private void RegisterSetterFunction(string varName)
|
||||
{
|
||||
_luaClientBehaviour.script.Globals["Set" + varName] = DynValue.NewCallback((context, args) =>
|
||||
{
|
||||
if (args.Count < 1) return DynValue.Nil;
|
||||
|
||||
var newValue = args[0];
|
||||
if (!IsSupportedDynValue(newValue))
|
||||
{
|
||||
LuaNetVarsMod.Logger.Error($"Unsupported DynValue type: {newValue.Type} for variable {varName}");
|
||||
return DynValue.Nil;
|
||||
}
|
||||
|
||||
if (_registeredNetworkVars.TryGetValue(varName, out var oldValue))
|
||||
{
|
||||
UpdateNetworkVariable(varName, oldValue, newValue);
|
||||
}
|
||||
|
||||
return DynValue.Nil;
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateNetworkVariable(string varName, DynValue oldValue, DynValue newValue)
|
||||
{
|
||||
_registeredNetworkVars[varName] = newValue;
|
||||
_luaClientBehaviour.script.Globals[varName] = newValue;
|
||||
_dirtyVariables.Add(varName);
|
||||
|
||||
if (_registeredNotifyCallbacks.TryGetValue(varName, out var callback))
|
||||
{
|
||||
_luaClientBehaviour.script.Call(callback, DynValue.NewString(varName), oldValue, newValue);
|
||||
}
|
||||
}
|
||||
|
||||
internal void RegisterNotifyCallback(string varName, DynValue callback)
|
||||
{
|
||||
if (!ValidateCallback(callback) || !ValidateNetworkVar(varName)) return;
|
||||
|
||||
if (_registeredNotifyCallbacks.ContainsKey(varName))
|
||||
LuaNetVarsMod.Logger.Warning($"Overwriting notify callback for {varName}");
|
||||
|
||||
_registeredNotifyCallbacks[varName] = callback;
|
||||
LuaNetVarsMod.Logger.Msg($"Registered notify callback for {varName}");
|
||||
}
|
||||
|
||||
internal void RegisterEventCallback(string eventName, DynValue callback)
|
||||
{
|
||||
if (!ValidateCallback(callback)) return;
|
||||
|
||||
if (_registeredEventCallbacks.ContainsKey(eventName))
|
||||
LuaNetVarsMod.Logger.Warning($"Overwriting event callback for {eventName}");
|
||||
|
||||
_registeredEventCallbacks[eventName] = callback;
|
||||
LuaNetVarsMod.Logger.Msg($"Registered event callback for {eventName}");
|
||||
}
|
||||
|
||||
private bool ValidateCallback(DynValue callback)
|
||||
{
|
||||
if (callback?.Function != null) return true;
|
||||
LuaNetVarsMod.Logger.Error("Passed DynValue must be a function");
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool ValidateNetworkVar(string varName)
|
||||
{
|
||||
if (_registeredNetworkVars.ContainsKey(varName)) return true;
|
||||
LuaNetVarsMod.Logger.Error($"Attempted to register notify callback for non-registered variable {varName}.");
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
using ABI_RC.Systems.ModNetwork;
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
public partial class LuaNetVarController
|
||||
{
|
||||
private static DynValue DeserializeDynValue(ModNetworkMessage msg)
|
||||
{
|
||||
msg.Read(out byte dataTypeByte);
|
||||
DataType dataType = (DataType)dataTypeByte;
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case DataType.Boolean:
|
||||
msg.Read(out bool boolValue);
|
||||
return DynValue.NewBoolean(boolValue);
|
||||
case DataType.Number:
|
||||
msg.Read(out double numberValue);
|
||||
return DynValue.NewNumber(numberValue);
|
||||
case DataType.String:
|
||||
msg.Read(out string stringValue);
|
||||
return DynValue.NewString(stringValue);
|
||||
case DataType.Nil:
|
||||
return DynValue.Nil;
|
||||
default:
|
||||
LuaNetVarsMod.Logger.Error($"Unsupported data type received: {dataType}");
|
||||
return DynValue.Nil;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SerializeDynValue(ModNetworkMessage msg, DynValue value)
|
||||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case DataType.Boolean:
|
||||
msg.Write((byte)DataType.Boolean);
|
||||
msg.Write(value.Boolean);
|
||||
break;
|
||||
case DataType.Number:
|
||||
msg.Write((byte)DataType.Number);
|
||||
msg.Write(value.Number);
|
||||
break;
|
||||
case DataType.String:
|
||||
msg.Write((byte)DataType.String);
|
||||
msg.Write(value.String);
|
||||
break;
|
||||
case DataType.Nil:
|
||||
msg.Write((byte)DataType.Nil);
|
||||
break;
|
||||
default:
|
||||
LuaNetVarsMod.Logger.Error($"Unsupported DynValue type: {value.Type}");
|
||||
msg.Write((byte)DataType.Nil);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsSupportedDynValue(DynValue value)
|
||||
{
|
||||
return value.Type is DataType.Boolean or DataType.Number or DataType.String or DataType.Nil;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
using ABI_RC.Core.Savior;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
public partial class LuaNetVarController
|
||||
{
|
||||
private bool TryGetUniqueNetworkID(out int hash)
|
||||
{
|
||||
string path = GetGameObjectPath(transform);
|
||||
hash = path.GetHashCode();
|
||||
|
||||
// Check if it already exists (this **should** only matter in worlds)
|
||||
if (_hashes.Contains(hash))
|
||||
{
|
||||
LuaNetVarsMod.Logger.Warning($"Duplicate RelativeSyncMarker found at path {path}");
|
||||
if (!FindAvailableHash(ref hash)) // Super lazy fix idfc
|
||||
{
|
||||
LuaNetVarsMod.Logger.Error($"Failed to find available hash for RelativeSyncMarker after 16 tries! {path}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
_hashes.Add(hash);
|
||||
|
||||
return true;
|
||||
|
||||
static bool FindAvailableHash(ref int hash)
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
hash += 1;
|
||||
if (!_hashes.Contains(hash)) return true;
|
||||
}
|
||||
return false; // Failed to find a hash in 16 tries
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetGameObjectPath(Transform transform)
|
||||
{
|
||||
string path = transform.name;
|
||||
while (transform.parent != null)
|
||||
{
|
||||
transform = transform.parent;
|
||||
|
||||
// Only true at root of local player object
|
||||
if (transform.CompareTag("Player"))
|
||||
{
|
||||
path = MetaPort.Instance.ownerId + "/" + path;
|
||||
break;
|
||||
}
|
||||
|
||||
path = transform.name + "/" + path;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue