NAK_CVR_Mods/.Experimental/LuaNetworkVariables/NetworkVariables/LuaNetVarController.Networking.cs
2025-04-03 03:03:24 -05:00

214 lines
No EOL
7.1 KiB
C#

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
}
}