mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-03 14:59:23 +00:00
[LuaNetworkVariables] Remove exp stuff, fix context properties
This commit is contained in:
parent
ece15e0dfc
commit
e85c1e2f25
10 changed files with 95 additions and 514 deletions
|
@ -18,24 +18,22 @@ public class LuaNetVarsMod : MelonMod
|
|||
public override void OnInitializeMelon()
|
||||
{
|
||||
Logger = LoggerInstance;
|
||||
|
||||
ApplyPatches(typeof(Patches.LuaScriptFactory_Patches));
|
||||
ApplyPatches(typeof(Patches.CVRSyncHelper_Patches));
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
// if (Input.GetKeyDown(KeyCode.F1))
|
||||
// {
|
||||
// PlayerSetup.Instance.DropProp("be0b5acc-a987-48dc-a28b-62bd912fe3a0");
|
||||
// }
|
||||
//
|
||||
// if (Input.GetKeyDown(KeyCode.F2))
|
||||
// {
|
||||
// GameObject go = new("TestSyncedObject");
|
||||
// go.AddComponent<TestSyncedObject>();
|
||||
// }
|
||||
}
|
||||
// public override void OnUpdate()
|
||||
// {
|
||||
// // if (Input.GetKeyDown(KeyCode.F1))
|
||||
// // {
|
||||
// // PlayerSetup.Instance.DropProp("be0b5acc-a987-48dc-a28b-62bd912fe3a0");
|
||||
// // }
|
||||
// //
|
||||
// // if (Input.GetKeyDown(KeyCode.F2))
|
||||
// // {
|
||||
// // GameObject go = new("TestSyncedObject");
|
||||
// // go.AddComponent<TestSyncedObject>();
|
||||
// // }
|
||||
// }
|
||||
|
||||
#endregion Melon Events
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
using ABI_RC.Core.Base;
|
||||
using ABI.Scripting.CVRSTL.Common;
|
||||
using JetBrains.Annotations;
|
||||
using NAK.LuaNetVars;
|
||||
using MoonSharp.Interpreter;
|
||||
|
||||
namespace NAK.LuaNetVars.Modules;
|
||||
|
||||
[PublicAPI] // Indicates that this class is used and should not be considered unused
|
||||
[PublicAPI]
|
||||
public class LuaNetModule : BaseScriptedStaticWrapper
|
||||
{
|
||||
public const string MODULE_ID = "NetworkModule";
|
||||
|
@ -102,6 +101,25 @@ public class LuaNetModule : BaseScriptedStaticWrapper
|
|||
_controller.SendLuaEvent(eventName, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a Lua event to other clients.
|
||||
/// </summary>
|
||||
/// <param name="eventName">The name of the event to send.</param>
|
||||
/// <param name="args">Optional arguments to send with the event.</param>
|
||||
public void SendLuaEventToUser(string eventName, string userId, params DynValue[] args)
|
||||
{
|
||||
CheckIfCanAccessMethod(nameof(SendLuaEventToUser), false,
|
||||
CVRLuaEnvironmentContext.CLIENT, CVRLuaObjectContext.ALL_BUT_EVENTS, CVRLuaOwnerContext.ANY);
|
||||
|
||||
if (_controller == null)
|
||||
{
|
||||
LuaNetVarsMod.Logger.Error("LuaNetVarController is null.");
|
||||
return;
|
||||
}
|
||||
|
||||
_controller.SendLuaEventToUser(eventName, userId, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the current client is the owner of the synchronized object.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using MoonSharp.Interpreter;
|
||||
using ABI_RC.Core.Networking;
|
||||
using MoonSharp.Interpreter;
|
||||
using ABI_RC.Core.Player;
|
||||
using ABI_RC.Core.Savior;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
|
@ -12,9 +12,9 @@ public struct LuaEventContext
|
|||
private double TimeSinceLastInvoke { get; set; }
|
||||
private bool IsLocal { get; set; }
|
||||
|
||||
public static LuaEventContext Create(string senderId, DateTime lastInvokeTime)
|
||||
public static LuaEventContext Create(bool isLocal, string senderId, DateTime lastInvokeTime)
|
||||
{
|
||||
var playerName = CVRPlayerManager.Instance.TryGetPlayerName(senderId);
|
||||
var playerName = isLocal ? AuthManager.Username : CVRPlayerManager.Instance.TryGetPlayerName(senderId);
|
||||
|
||||
return new LuaEventContext
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ public struct LuaEventContext
|
|||
SenderName = playerName ?? "Unknown",
|
||||
LastInvokeTime = lastInvokeTime,
|
||||
TimeSinceLastInvoke = (DateTime.Now - lastInvokeTime).TotalSeconds,
|
||||
IsLocal = senderId == MetaPort.Instance.ownerId
|
||||
IsLocal = isLocal
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -30,11 +30,11 @@ public struct LuaEventContext
|
|||
{
|
||||
Table table = new(script)
|
||||
{
|
||||
["senderId"] = SenderId,
|
||||
["senderName"] = SenderName,
|
||||
["lastInvokeTime"] = LastInvokeTime.ToUniversalTime().ToString("O"),
|
||||
["timeSinceLastInvoke"] = TimeSinceLastInvoke,
|
||||
["isLocal"] = IsLocal
|
||||
["SenderId"] = SenderId,
|
||||
["SenderName"] = SenderName,
|
||||
["LastInvokeTime"] = LastInvokeTime.ToUniversalTime().ToString("O"),
|
||||
["TimeSinceLastInvoke"] = TimeSinceLastInvoke,
|
||||
["IsLocal"] = IsLocal
|
||||
};
|
||||
return table;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using ABI.CCK.Components;
|
|||
using ABI.Scripting.CVRSTL.Common;
|
||||
using MoonSharp.Interpreter;
|
||||
using UnityEngine;
|
||||
using Coroutine = UnityEngine.Coroutine;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
|
@ -27,21 +28,23 @@ public partial class LuaNetVarController : MonoBehaviour
|
|||
private CVRSpawnable _spawnable;
|
||||
private CVRObjectSync _objectSync;
|
||||
|
||||
private bool _isInitialized;
|
||||
private Coroutine _syncCoroutine;
|
||||
|
||||
#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());
|
||||
}
|
||||
=> _isInitialized = Initialize();
|
||||
|
||||
private void OnDestroy()
|
||||
=> Cleanup();
|
||||
|
||||
private void OnEnable()
|
||||
=> StartStopVariableUpdatesCoroutine(true);
|
||||
|
||||
private void OnDisable()
|
||||
=> StartStopVariableUpdatesCoroutine(false);
|
||||
|
||||
#endregion Unity Events
|
||||
|
||||
#region Private Methods
|
||||
|
@ -102,9 +105,16 @@ public partial class LuaNetVarController : MonoBehaviour
|
|||
_hashes.Remove(_uniquePathHash);
|
||||
}
|
||||
|
||||
private void StartStopVariableUpdatesCoroutine(bool start)
|
||||
{
|
||||
if (_syncCoroutine != null) StopCoroutine(_syncCoroutine);
|
||||
_syncCoroutine = null;
|
||||
if (start) _syncCoroutine = StartCoroutine(SendVariableUpdatesCoroutine());
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator SendVariableUpdatesCoroutine()
|
||||
{
|
||||
while (true)
|
||||
while (isActiveAndEnabled)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
if (IsSyncOwner()) SendVariableUpdates();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.ModNetwork;
|
||||
using MoonSharp.Interpreter;
|
||||
using Unity.Services.Authentication.Internal;
|
||||
|
||||
namespace NAK.LuaNetVars
|
||||
{
|
||||
|
@ -66,7 +65,7 @@ namespace NAK.LuaNetVars
|
|||
msg.Read(out int argsCount);
|
||||
|
||||
DateTime lastInvokeTime = _eventTracker.GetLastInvokeTimeForSender(eventName, senderId);
|
||||
LuaEventContext context = LuaEventContext.Create(senderId, lastInvokeTime);
|
||||
LuaEventContext context = LuaEventContext.Create(false, senderId, lastInvokeTime);
|
||||
|
||||
// Update tracking
|
||||
_eventTracker.UpdateInvokeTime(eventName, senderId);
|
||||
|
@ -187,7 +186,7 @@ namespace NAK.LuaNetVars
|
|||
{
|
||||
string senderId = MetaPort.Instance.ownerId;
|
||||
DateTime lastInvokeTime = _eventTracker.GetLastInvokeTimeForSender(eventName, senderId);
|
||||
LuaEventContext context = LuaEventContext.Create(senderId, lastInvokeTime);
|
||||
LuaEventContext context = LuaEventContext.Create(true, senderId, lastInvokeTime);
|
||||
|
||||
// Update tracking
|
||||
_eventTracker.UpdateInvokeTime(eventName, senderId);
|
||||
|
@ -209,6 +208,32 @@ namespace NAK.LuaNetVars
|
|||
modMsg.Send();
|
||||
}
|
||||
|
||||
internal void SendLuaEventToUser(string eventName, string userId, DynValue[] args)
|
||||
{
|
||||
string senderId = MetaPort.Instance.ownerId;
|
||||
DateTime lastInvokeTime = _eventTracker.GetLastInvokeTimeForSender(eventName, senderId);
|
||||
LuaEventContext context = LuaEventContext.Create(true, 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, userId);
|
||||
modMsg.Write((byte)MessageType.LuaEvent);
|
||||
modMsg.Write(eventName);
|
||||
modMsg.Write(args.Length);
|
||||
|
||||
foreach (DynValue arg in args)
|
||||
SerializeDynValue(modMsg, arg);
|
||||
|
||||
modMsg.Send();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
using ABI_RC.Core.Base;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Core.Util;
|
||||
using ABI.CCK.Components;
|
||||
using ABI.Scripting.CVRSTL.Client;
|
||||
using ABI.Scripting.CVRSTL.Client;
|
||||
using ABI.Scripting.CVRSTL.Common;
|
||||
using HarmonyLib;
|
||||
using MoonSharp.Interpreter;
|
||||
using NAK.LuaNetVars.Modules;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.LuaNetVars.Patches;
|
||||
|
||||
|
@ -29,37 +24,3 @@ internal static class LuaScriptFactory_Patches
|
|||
__instance.RegisteredModules[LuaNetModule.MODULE_ID] = __result; // add module to cache
|
||||
}
|
||||
}
|
||||
|
||||
internal static class CVRSyncHelper_Patches
|
||||
{
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(typeof(CVRSyncHelper), nameof(CVRSyncHelper.UpdatePropValues))]
|
||||
private static void Postfix_CVRSyncHelper_UpdatePropValues(
|
||||
Vector3 position, Vector3 rotation, Vector3 scale,
|
||||
float[] syncValues, string guid, string instanceId,
|
||||
Span<float> subSyncValues, int numSyncValues, int syncType = 0)
|
||||
{
|
||||
CVRSyncHelper.PropData propData = CVRSyncHelper.Props.Find(prop => prop.InstanceId == instanceId);
|
||||
if (propData == null) return;
|
||||
|
||||
// Update locally stored prop data with new values
|
||||
// as GS does not reply with our own data...
|
||||
|
||||
propData.PositionX = position.x;
|
||||
propData.PositionY = position.y;
|
||||
propData.PositionZ = position.z;
|
||||
propData.RotationX = rotation.x;
|
||||
propData.RotationY = rotation.y;
|
||||
propData.RotationZ = rotation.z;
|
||||
propData.ScaleX = scale.x;
|
||||
propData.ScaleY = scale.y;
|
||||
propData.ScaleZ = scale.z;
|
||||
propData.CustomFloatsAmount = numSyncValues;
|
||||
for (int i = 0; i < numSyncValues; i++)
|
||||
propData.CustomFloats[i] = syncValues[i];
|
||||
|
||||
//propData.SpawnedBy
|
||||
propData.syncedBy = MetaPort.Instance.ownerId;
|
||||
propData.syncType = syncType;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ using System.Reflection;
|
|||
nameof(NAK.LuaNetVars),
|
||||
AssemblyInfoParams.Version,
|
||||
AssemblyInfoParams.Author,
|
||||
downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/WhereAmIPointing"
|
||||
downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/LuaNetworkVariables"
|
||||
)]
|
||||
|
||||
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
|
||||
|
@ -27,6 +27,6 @@ using System.Reflection;
|
|||
namespace NAK.LuaNetVars.Properties;
|
||||
internal static class AssemblyInfoParams
|
||||
{
|
||||
public const string Version = "1.0.0";
|
||||
public const string Version = "1.0.1";
|
||||
public const string Author = "NotAKidoS";
|
||||
}
|
|
@ -1,326 +0,0 @@
|
|||
using UnityEngine;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using ABI_RC.Core.Savior;
|
||||
using ABI_RC.Systems.ModNetwork;
|
||||
|
||||
namespace NAK.LuaNetVars
|
||||
{
|
||||
public abstract class MNSyncedBehaviour : IDisposable
|
||||
{
|
||||
// Add static property for clarity
|
||||
protected static string LocalUserId => MetaPort.Instance.ownerId;
|
||||
|
||||
protected enum MessageType : byte
|
||||
{
|
||||
OwnershipRequest,
|
||||
OwnershipResponse,
|
||||
OwnershipTransfer,
|
||||
StateRequest,
|
||||
StateUpdate,
|
||||
CustomData
|
||||
}
|
||||
|
||||
protected enum OwnershipResponse : byte
|
||||
{
|
||||
Accepted,
|
||||
Rejected
|
||||
}
|
||||
|
||||
protected readonly string networkId;
|
||||
protected string currentOwnerId;
|
||||
private readonly bool autoAcceptTransfers;
|
||||
private readonly Dictionary<string, Action<bool>> pendingRequests;
|
||||
private bool isInitialized;
|
||||
private bool disposedValue;
|
||||
private bool isSoftOwner = false;
|
||||
private Timer stateRequestTimer;
|
||||
private const int StateRequestTimeout = 3000; // 3 seconds
|
||||
|
||||
public string CurrentOwnerId => currentOwnerId;
|
||||
public bool HasOwnership => currentOwnerId == LocalUserId;
|
||||
|
||||
protected MNSyncedBehaviour(string networkId, string currentOwnerId = "", bool autoAcceptTransfers = false)
|
||||
{
|
||||
this.networkId = networkId;
|
||||
this.currentOwnerId = currentOwnerId;
|
||||
this.autoAcceptTransfers = autoAcceptTransfers;
|
||||
this.pendingRequests = new Dictionary<string, Action<bool>>();
|
||||
|
||||
ModNetworkManager.Subscribe(networkId, OnMessageReceived);
|
||||
|
||||
if (!HasOwnership)
|
||||
RequestInitialState();
|
||||
else
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
private void RequestInitialState()
|
||||
{
|
||||
using ModNetworkMessage msg = new(networkId);
|
||||
msg.Write((byte)MessageType.StateRequest);
|
||||
msg.Send();
|
||||
|
||||
stateRequestTimer = new Timer(StateRequestTimeoutCallback, null, StateRequestTimeout, Timeout.Infinite);
|
||||
}
|
||||
|
||||
private void StateRequestTimeoutCallback(object state)
|
||||
{
|
||||
// If isInitialized is still false, we assume soft ownership
|
||||
if (!isInitialized)
|
||||
{
|
||||
currentOwnerId = LocalUserId;
|
||||
isSoftOwner = true;
|
||||
isInitialized = true;
|
||||
OnOwnershipChanged(currentOwnerId);
|
||||
}
|
||||
|
||||
stateRequestTimer.Dispose();
|
||||
stateRequestTimer = null;
|
||||
}
|
||||
|
||||
public virtual void RequestOwnership(Action<bool> callback = null)
|
||||
{
|
||||
if (HasOwnership)
|
||||
{
|
||||
callback?.Invoke(true);
|
||||
return;
|
||||
}
|
||||
|
||||
using (ModNetworkMessage msg = new(networkId))
|
||||
{
|
||||
msg.Write((byte)MessageType.OwnershipRequest);
|
||||
msg.Send();
|
||||
}
|
||||
|
||||
if (callback != null)
|
||||
{
|
||||
pendingRequests[LocalUserId] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
protected void SendNetworkedData(Action<ModNetworkMessage> writeData)
|
||||
{
|
||||
if (!HasOwnership)
|
||||
{
|
||||
Debug.LogWarning($"[MNSyncedBehaviour] Cannot send data without ownership. NetworkId: {networkId}");
|
||||
return;
|
||||
}
|
||||
|
||||
using (ModNetworkMessage msg = new(networkId))
|
||||
{
|
||||
msg.Write((byte)MessageType.CustomData);
|
||||
writeData(msg);
|
||||
msg.Send();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnMessageReceived(ModNetworkMessage message)
|
||||
{
|
||||
message.Read(out byte type);
|
||||
MessageType messageType = (MessageType)type;
|
||||
|
||||
if (!Enum.IsDefined(typeof(MessageType), messageType))
|
||||
return;
|
||||
|
||||
switch (messageType)
|
||||
{
|
||||
case MessageType.OwnershipRequest:
|
||||
if (!HasOwnership) break;
|
||||
HandleOwnershipRequest(message);
|
||||
break;
|
||||
|
||||
case MessageType.OwnershipResponse:
|
||||
if (message.Sender != currentOwnerId) break;
|
||||
HandleOwnershipResponse(message);
|
||||
break;
|
||||
|
||||
case MessageType.OwnershipTransfer:
|
||||
if (message.Sender != currentOwnerId) break;
|
||||
currentOwnerId = message.Sender;
|
||||
OnOwnershipChanged(currentOwnerId);
|
||||
break;
|
||||
|
||||
case MessageType.StateRequest:
|
||||
if (!HasOwnership) break; // this is the only safeguard against ownership hijacking... idk how to prevent it
|
||||
// TODO: only respond to a StateUpdate if expecting one
|
||||
HandleStateRequest(message);
|
||||
break;
|
||||
|
||||
case MessageType.StateUpdate:
|
||||
// Accept state updates from current owner or if we have soft ownership
|
||||
if (message.Sender != currentOwnerId && !isSoftOwner) break;
|
||||
HandleStateUpdate(message);
|
||||
break;
|
||||
|
||||
case MessageType.CustomData:
|
||||
if (message.Sender != currentOwnerId)
|
||||
{
|
||||
// If we have soft ownership and receive data from real owner, accept it
|
||||
if (isSoftOwner && message.Sender != LocalUserId)
|
||||
{
|
||||
currentOwnerId = message.Sender;
|
||||
isSoftOwner = false;
|
||||
OnOwnershipChanged(currentOwnerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore data from non-owner
|
||||
break;
|
||||
}
|
||||
}
|
||||
HandleCustomData(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleOwnershipRequest(ModNetworkMessage message)
|
||||
{
|
||||
if (!HasOwnership)
|
||||
return;
|
||||
|
||||
string requesterId = message.Sender;
|
||||
var response = autoAcceptTransfers ? OwnershipResponse.Accepted :
|
||||
OnOwnershipRequested(requesterId);
|
||||
|
||||
using (ModNetworkMessage responseMsg = new(networkId))
|
||||
{
|
||||
responseMsg.Write((byte)MessageType.OwnershipResponse);
|
||||
responseMsg.Write((byte)response);
|
||||
responseMsg.Send();
|
||||
}
|
||||
|
||||
if (response == OwnershipResponse.Accepted)
|
||||
{
|
||||
TransferOwnership(requesterId);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleOwnershipResponse(ModNetworkMessage message)
|
||||
{
|
||||
message.Read(out byte responseByte);
|
||||
OwnershipResponse response = (OwnershipResponse)responseByte;
|
||||
|
||||
if (pendingRequests.TryGetValue(LocalUserId, out var callback))
|
||||
{
|
||||
bool accepted = response == OwnershipResponse.Accepted;
|
||||
callback(accepted);
|
||||
pendingRequests.Remove(LocalUserId);
|
||||
|
||||
// Update ownership locally only if accepted
|
||||
if (accepted)
|
||||
{
|
||||
currentOwnerId = LocalUserId;
|
||||
OnOwnershipChanged(currentOwnerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleStateRequest(ModNetworkMessage message)
|
||||
{
|
||||
if (!HasOwnership)
|
||||
return;
|
||||
|
||||
using ModNetworkMessage response = new(networkId, message.Sender);
|
||||
response.Write((byte)MessageType.StateUpdate);
|
||||
WriteState(response);
|
||||
response.Send();
|
||||
}
|
||||
|
||||
protected virtual void HandleStateUpdate(ModNetworkMessage message)
|
||||
{
|
||||
currentOwnerId = message.Sender;
|
||||
isSoftOwner = false;
|
||||
ReadState(message);
|
||||
isInitialized = true;
|
||||
|
||||
// Dispose of the state request timer if it's still running
|
||||
if (stateRequestTimer != null)
|
||||
{
|
||||
stateRequestTimer.Dispose();
|
||||
stateRequestTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleCustomData(ModNetworkMessage message)
|
||||
{
|
||||
if (!isInitialized)
|
||||
{
|
||||
Debug.LogWarning($"[MNSyncedBehaviour] Received custom data before initialization. NetworkId: {networkId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.Sender != currentOwnerId)
|
||||
{
|
||||
// If we have soft ownership and receive data from real owner, accept it
|
||||
if (isSoftOwner && message.Sender != LocalUserId)
|
||||
{
|
||||
currentOwnerId = message.Sender;
|
||||
isSoftOwner = false;
|
||||
OnOwnershipChanged(currentOwnerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Ignore data from non-owner
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ReadCustomData(message);
|
||||
}
|
||||
|
||||
protected virtual void TransferOwnership(string newOwnerId)
|
||||
{
|
||||
using (ModNetworkMessage msg = new(networkId))
|
||||
{
|
||||
msg.Write((byte)MessageType.OwnershipTransfer);
|
||||
msg.Write(newOwnerId); // Include the new owner ID in transfer message
|
||||
msg.Send();
|
||||
}
|
||||
|
||||
currentOwnerId = newOwnerId;
|
||||
OnOwnershipChanged(newOwnerId);
|
||||
}
|
||||
|
||||
protected virtual OwnershipResponse OnOwnershipRequested(string requesterId)
|
||||
{
|
||||
return OwnershipResponse.Rejected;
|
||||
}
|
||||
|
||||
protected virtual void OnOwnershipChanged(string newOwnerId)
|
||||
{
|
||||
// Override to handle ownership changes
|
||||
}
|
||||
|
||||
protected virtual void WriteState(ModNetworkMessage message) { }
|
||||
protected virtual void ReadState(ModNetworkMessage message) { }
|
||||
protected virtual void ReadCustomData(ModNetworkMessage message) { }
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (disposedValue)
|
||||
return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
ModNetworkManager.Unsubscribe(networkId);
|
||||
pendingRequests.Clear();
|
||||
|
||||
if (stateRequestTimer != null)
|
||||
{
|
||||
stateRequestTimer.Dispose();
|
||||
stateRequestTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
using ABI_RC.Systems.ModNetwork;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
|
||||
// Test implementation
|
||||
public class TestSyncedBehaviour : MNSyncedBehaviour
|
||||
{
|
||||
private readonly System.Random random = new();
|
||||
private int testValue;
|
||||
private int incrementValue;
|
||||
|
||||
public TestSyncedBehaviour(string networkId) : base(networkId, autoAcceptTransfers: true)
|
||||
{
|
||||
Debug.Log($"[TestSyncedBehaviour] Initialized. NetworkId: {networkId}");
|
||||
}
|
||||
|
||||
public void SendTestMessage()
|
||||
{
|
||||
if (!HasOwnership) return;
|
||||
|
||||
SendNetworkedData(msg => {
|
||||
testValue = random.Next(1000);
|
||||
incrementValue++;
|
||||
msg.Write(testValue);
|
||||
msg.Write(incrementValue);
|
||||
});
|
||||
}
|
||||
|
||||
protected override void WriteState(ModNetworkMessage message)
|
||||
{
|
||||
message.Write(testValue);
|
||||
message.Write(incrementValue);
|
||||
}
|
||||
|
||||
protected override void ReadState(ModNetworkMessage message)
|
||||
{
|
||||
message.Read(out testValue);
|
||||
message.Read(out incrementValue);
|
||||
Debug.Log($"[TestSyncedBehaviour] State synchronized. TestValue: {testValue}, IncrementValue: {incrementValue}");
|
||||
}
|
||||
|
||||
protected override void ReadCustomData(ModNetworkMessage message)
|
||||
{
|
||||
message.Read(out int receivedValue);
|
||||
message.Read(out int receivedIncrement);
|
||||
testValue = receivedValue;
|
||||
incrementValue = receivedIncrement;
|
||||
Debug.Log($"[TestSyncedBehaviour] Received custom data: TestValue: {testValue}, IncrementValue: {incrementValue}");
|
||||
}
|
||||
|
||||
protected override void OnOwnershipChanged(string newOwnerId)
|
||||
{
|
||||
Debug.Log($"[TestSyncedBehaviour] Ownership changed to: {newOwnerId}");
|
||||
}
|
||||
|
||||
protected override OwnershipResponse OnOwnershipRequested(string requesterId)
|
||||
{
|
||||
Debug.Log($"[TestSyncedBehaviour] Ownership requested by: {requesterId}");
|
||||
return OwnershipResponse.Accepted;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
using ABI_RC.Core.Savior;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NAK.LuaNetVars;
|
||||
|
||||
public class TestSyncedObject : MonoBehaviour
|
||||
{
|
||||
private const string TEST_NETWORK_ID = "test.synced.object.1";
|
||||
private TestSyncedBehaviour syncBehaviour;
|
||||
private float messageTimer = 0f;
|
||||
private const float MESSAGE_INTERVAL = 2f;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
syncBehaviour = new TestSyncedBehaviour(TEST_NETWORK_ID);
|
||||
Debug.Log($"TestSyncedObject started. Local Player ID: {MetaPort.Instance.ownerId}");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Request ownership on Space key
|
||||
if (Input.GetKeyDown(KeyCode.Space))
|
||||
{
|
||||
Debug.Log("Requesting ownership...");
|
||||
syncBehaviour.RequestOwnership((success) =>
|
||||
{
|
||||
Debug.Log($"Ownership request {(success ? "accepted" : "rejected")}");
|
||||
});
|
||||
}
|
||||
|
||||
// If we have ownership, send custom data periodically
|
||||
if (syncBehaviour.HasOwnership)
|
||||
{
|
||||
messageTimer += Time.deltaTime;
|
||||
if (messageTimer >= MESSAGE_INTERVAL)
|
||||
{
|
||||
messageTimer = 0f;
|
||||
syncBehaviour.SendTestMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue