more sync stuff

This commit is contained in:
Aaro Varis
2025-03-02 17:35:20 +02:00
parent fc744fd1ab
commit 7f266321db
12 changed files with 184 additions and 41 deletions

View File

@@ -7,6 +7,7 @@ using UnityEngine;
using BoneSync.Player;
using BoneSync.Sync;
using Facepunch.Steamworks;
using System.Reflection.Emit;
namespace BoneSync
{
@@ -52,6 +53,7 @@ namespace BoneSync
public override void OnSceneWasInitialized(int buildIndex, string sceneName)
{
//MelonLogger.Msg("OnLevelWasInitialized: " + sceneName);
SceneSync.OnSceneInit(buildIndex);
}
public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
@@ -76,11 +78,6 @@ namespace BoneSync
}
}
public override void OnLevelWasInitialized(int level)
{
SceneSync.OnSceneInit(level);
}
public override void BONEWORKS_OnLoadingScreen()
{
base.BONEWORKS_OnLoadingScreen();

View File

@@ -5,12 +5,14 @@ using System.Text;
using System.Threading.Tasks;
using BoneSync.Sync;
using BoneSync.Sync.Components;
using MelonLoader;
namespace BoneSync.Networking.Messages
{
public struct DiscardSyncableMessageData
{
public ushort syncId;
public bool despawn;
}
[PacketType(PacketType.DiscardSyncable), PacketReliability(PacketReliability.ReliableFast)]
internal class DiscardSyncableMessage : NetworkMessage
@@ -21,20 +23,26 @@ namespace BoneSync.Networking.Messages
{
_data = discardSyncableMessageData;
byteEncoder.WriteUShort(_data.syncId);
byteEncoder.WriteBool(_data.despawn);
}
public DiscardSyncableMessage(Packet packet)
{
byteEncoder.WriteBytes(packet.Data);
_data.syncId = byteEncoder.ReadUShort();
_data.despawn = byteEncoder.ReadBool();
}
public override void Execute()
{
Syncable syncable = ObjectSyncCache.GetSyncable(_data.syncId);
if (syncable != null)
{
syncable.DiscardSyncable(true);
syncable.DiscardSyncable(true, _data.despawn);
} else
{
MelonLogger.Warning(senderId + " tried to discard a syncable that doesn't exist (syncId: " + _data.syncId + ")");
}
}

View File

@@ -16,6 +16,8 @@ namespace BoneSync.Networking.Messages
public bool[] _attributes;
public ObjectMagazineData? magazineData;
}
[PacketType(PacketType.ObjectAttribute), PacketReliability(PacketReliability.ReliableFast)]
internal class ObjectAttributeMessage : NetworkMessage
{
private ObjectAttributeMessageData _data;
@@ -26,8 +28,8 @@ namespace BoneSync.Networking.Messages
_data = objectAttributeMessageData;
byteEncoder.WriteUShort(_data.syncId);
attributes.Add(_data.magazineData != null);
if (_data.magazineData != null)
attributes.Add(_data.magazineData.HasValue);
if (_data.magazineData.HasValue)
{
byteEncoder.WriteByte(_data.magazineData.Value.ammoCount);
}

View File

@@ -16,5 +16,6 @@ namespace BoneSync.Networking
ObjectEvent = 5,
ObjectOwnership = 6,
DiscardSyncable = 7,
ObjectAttribute = 8,
}
}

View File

@@ -31,6 +31,13 @@ namespace BoneSync.Patching
allowPatchedMethodCall = false;
}
public static void Despawn(Poolee poolee)
{
allowPatchedMethodCall = true;
poolee.Despawn();
allowPatchedMethodCall = false;
}
public static Poolee InstantiatePoolee(Pool pool, Vector3 position, Quaternion rotation, Vector3 scale)
{
allowPatchedMethodCall = true;

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BoneSync.Sync;
using BoneSync.Sync.Components;
using HarmonyLib;
using StressLevelZero.Interaction;
namespace BoneSync.Patching
@@ -15,7 +16,13 @@ namespace BoneSync.Patching
public static void OnEnablePatch(ForcePullGrip __instance)
{
MelonLoader.MelonLogger.Msg("ForcePullGrip.Pull: " + __instance.name);
ObjectSync.MakeOrGetSyncable(__instance.gameObject);
InteractableHost interactableHost = __instance.GetComponent<InteractableHost>();
if (interactableHost == null) return;
Syncable syncable = ObjectSync.MakeOrGetSyncable(interactableHost);
if (syncable)
{
syncable.RegisterSyncable();
}
}
}

View File

@@ -79,6 +79,7 @@ namespace BoneSync.Patching
if (PoolBlacklist.isBlacklistedPool(__instance)) return;
MelonLogger.Msg("Patched Instantiating object in pool: " + __instance.name);
__result.onSpawnDelegate = Il2CppSystem.Delegate.Combine(__result.onSpawnDelegate, (Il2CppSystem.Action<GameObject>)((g) => { PooleePatches.OnSpawnPatchPost(__result); })).Cast<Il2CppSystem.Action<GameObject>>();
__result.onDespawnDelegate = Il2CppSystem.Delegate.Combine(__result.onDespawnDelegate, (Il2CppSystem.Action<GameObject>)((g) => { PooleePatches.OnDespawnPatchPost(__result); })).Cast<Il2CppSystem.Action<GameObject>>();
}
@@ -140,6 +141,22 @@ namespace BoneSync.Patching
}
public static void OnDespawnPatchPost(Poolee __instance)
{
if (CallPatchedMethods.allowPatchedMethodCall) return;
if (!BoneSync.lobby.IsConnected()) return;
MelonLogger.Msg("Poolee.OnDespawn: " + __instance.gameObject.transform.GetPath());
//Syncable syncable = ObjectSync.MakeOrGetSyncable(__instance);
//if (syncable == null) return;
//if (syncable.isOwner) return;
//syncable.DiscardSyncable(true);
}
public static IEnumerator OnSpawnClient(Poolee poolee)
{
GameObject go = poolee.gameObject;

View File

@@ -31,6 +31,28 @@ namespace BoneSync.Sync.Components
return "/" + current.name;
return current.parent.GetPath() + "/" + current.name;
}
public static Transform TransformFromPath(string path)
{
if (path.StartsWith("/"))
{
path = path.Substring(1);
}
string[] pathParts = path.Split('/');
Transform current = null;
foreach (string part in pathParts)
{
if (current == null)
{
current = GameObject.Find(part).transform;
}
else
{
current = current.Find(part);
}
}
return current;
}
}
[RegisterTypeInIl2Cpp]
@@ -92,15 +114,20 @@ namespace BoneSync.Sync.Components
private SpawnFragment spawnFragment;
private IEnumerator _CheckAutoSyncCo()
private void CheckAutoSync()
{
yield return null;
bool shouldAutoSync = CheckIfShouldAutoSync();
if (shouldAutoSync && (BoneSync.lobby.IsHost || ClientSpawningAllowed()))
{
MelonLogger.Msg("AutoSyncing: " + transform.GetPath());
RegisterSyncable();
}
}
private IEnumerator _OnEnableCo()
{
yield return null; // wait a frame to make sure all components are initialized, I hate this but it works
FindComponents();
CheckAutoSync();
yield break;
}
@@ -110,11 +137,15 @@ namespace BoneSync.Sync.Components
FindComponents();
MelonCoroutines.Start(_CheckAutoSyncCo());
MelonCoroutines.Start(_OnEnableCo());
}
public bool CheckIfShouldAutoSync()
{
if (transform.GetPath().StartsWith("/Pool Manager/"))
{
return false;
}
if (poolee && poolee.pool) {
return true;
}
@@ -129,7 +160,7 @@ namespace BoneSync.Sync.Components
}
if (interactableHost || interactableManager)
{
return transform.GetPath().Replace(" ", "[]");
return transform.GetPath();
}
return "";
}
@@ -153,6 +184,13 @@ namespace BoneSync.Sync.Components
ObjectSyncCache.AddSyncable(this);
}
private void ResetSyncStatus()
{
_ownerId = 0;
_syncId = 0;
_attemptedRegister = false;
SetKinematic(false);
}
public bool CanBeSynced()
{
if (spawnFragment) return false; // if has spawn fragment, don't sync
@@ -162,24 +200,38 @@ namespace BoneSync.Sync.Components
return false;
}
private void _DiscardSyncable(bool force)
private void _DiscardSyncable(bool force, bool despawn)
{
if (Registered)
bool isRegistered = Registered;
MelonLogger.Msg("Discarding syncable: " + transform.GetPath() + " force: " + force + " isRegistered: " + isRegistered + " despawn: " + despawn);
if (isRegistered)
{
MelonLogger.Warning("Discarding registered syncable: " + transform.GetPath() + " force: " + force);
//MelonLogger.Warning("Discarding registered syncable: " + transform.GetPath() + " force: " + force);
bool isowner = isOwner;
if (isowner)
{
_SendDiscard(); // owner sends discard message
_SendDiscard(true); // owner sends discard message
}
if (!isowner && !force) return; // only owner can discard
}
syncablesCache.Remove(gameObject);
if (gameObject) syncablesCache.Remove(gameObject);
ObjectSyncCache.RemoveSyncable(this);
Destroy(this); // delete the component
ResetSyncStatus();
DestroyImmediate(this); // delete the component
if (despawn)
{
gameObject?.SetActive(false);
}
}
public void OnDestroy()
@@ -188,19 +240,25 @@ namespace BoneSync.Sync.Components
{
MelonLogger.Warning("Destroying registered syncable: " + transform.GetPath());
}
_DiscardSyncable(true);
DiscardSyncableImmediate(true, Registered);
//MelonLogger.Msg("Syncable destroyed: " + transform.GetPath());
}
private IEnumerator _FlagForDiscardCo(bool force)
private IEnumerator _FlagForDiscardCo(bool force, bool despawn) { yield return null; _DiscardSyncable(force, despawn); } // delay discard to prevent silly behavior
public void DiscardSyncable(bool force = false, bool despawn = false)
{
yield return null;
_DiscardSyncable(force);
if (Registered && isOwner)
{
DiscardSyncableImmediate(force, despawn);
return;
}
MelonCoroutines.Start(_FlagForDiscardCo(force, despawn));
}
public void DiscardSyncable(bool force = false)
public void DiscardSyncableImmediate(bool force = false, bool despawn = false)
{
MelonCoroutines.Start(_FlagForDiscardCo(force));
_DiscardSyncable(true, despawn);
}
public void OnDisable()
@@ -209,10 +267,9 @@ namespace BoneSync.Sync.Components
{
MelonLogger.Warning("tried to disable non-owner syncable: " + transform.GetPath());
gameObject.SetActive(true);
} else
{
DiscardSyncable();
return;
}
DiscardSyncable();
}
public void RegisterSyncable()

View File

@@ -56,11 +56,13 @@ namespace BoneSync.Sync.Components
SetSyncId(ObjectSync.SendRegisterSyncableMessage(this));
}
private void _SendDiscard()
private void _SendDiscard(bool despawn = false)
{
MelonLogger.Msg("Sending discard for " + _syncId + " despawn: " + despawn);
DiscardSyncableMessageData discardSyncableMessageData = new DiscardSyncableMessageData()
{
syncId = _syncId
syncId = _syncId,
despawn = despawn
};
DiscardSyncableMessage discardSyncableMessage = new DiscardSyncableMessage(discardSyncableMessageData);
discardSyncableMessage.Broadcast();
@@ -85,7 +87,7 @@ namespace BoneSync.Sync.Components
public void TryBecomeOwner()
{
if (!isOwner)
if (Registered && !isOwner)
{
MelonLogger.Msg("Attempting to become owner of " + _syncId);
OwnershipTransferMessageData data = new OwnershipTransferMessageData()

View File

@@ -105,12 +105,6 @@ namespace BoneSync.Sync
//Scene scene = gameObject.scene;
//MelonLogger.Msg("Making or getting syncable for: " + gameObject.name + " in scene: " + scene.name);
Syncable parentSyncable = gameObject.transform.parent.GetComponentInParent<Syncable>();
if (parentSyncable != null)
{
return parentSyncable;
}
Syncable syncable = gameObject.GetComponent<Syncable>();
// delete all sub syncables
@@ -210,6 +204,12 @@ namespace BoneSync.Sync
}
}
if (info.id == 0)
{
MelonLogger.Warning("Received register sync message with id 0");
return;
}
bool hasCallback = info.callbackId != 0;
if (hasCallback)
{
@@ -250,6 +250,9 @@ namespace BoneSync.Sync
{
ObjectSyncMessageData data = objectSyncMessage.objectSyncMessageData;
ushort objectId = data.objectId;
if (objectId == 0) return;
if (objectId >= _nextSyncableId && !BoneSync.lobby.IsHost)
{
_nextSyncableId = (ushort)(objectId + 1);
@@ -257,7 +260,7 @@ namespace BoneSync.Sync
Syncable syncable = ObjectSyncCache.GetSyncable(objectId);
if (syncable == null)
{
MelonLogger.Msg("SyncEvent: Syncable not found for id: " + objectId);
//MelonLogger.Msg("SyncEvent: Syncable not found for id: " + objectId);
return;
}
syncable.ApplyObjectSyncTransforms(data.objectSyncTransforms);

View File

@@ -6,6 +6,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace BoneSync.Sync
{
@@ -86,6 +87,11 @@ namespace BoneSync.Sync
{
return _pathToSyncable[path];
}
Transform transform = TransformExtensions.TransformFromPath(path);
if (transform)
{
return transform.GetComponent<Syncable>();
}
return null;
}

View File

@@ -1,9 +1,12 @@
using MelonLoader;
using BoneSync.Sync.Components;
using MelonLoader;
using StressLevelZero.Interaction;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace BoneSync.Sync
@@ -27,12 +30,45 @@ namespace BoneSync.Sync
return sceneName;
}
}
public static void RenameDuplicateSceneTransforms(Scene scene)
{
Dictionary<string, ushort> seenTransformNames = new Dictionary<string, ushort>();
uint total = 0;
foreach (GameObject go in scene.GetRootGameObjects())
{
foreach (InteractableHost host in go.GetComponentsInChildren<InteractableHost>(true))
{
Transform t = host.transform;
string path = t.GetPath();
if (seenTransformNames.ContainsKey(path))
{
seenTransformNames[path]++;
t.name = t.name + " (BoneSync." + seenTransformNames[path] + ")";
total++;
//MelonLogger.Msg("Renamed duplicate transform: " + path);
}
else
{
seenTransformNames[path] = 1;
}
}
}
MelonLogger.Msg("Renamed " + total + " duplicate transforms in " + scene.name);
}
public static void OnSceneInit(int buildIndex)
{
string SceneName = SceneManager.GetSceneByBuildIndex(buildIndex).name;
Scene scene = SceneManager.GetSceneByBuildIndex(buildIndex);
string SceneName = scene.name;
_currentSceneName = SceneName;
MelonLogger.Msg("Scene initialized: " + SceneName);
RenameDuplicateSceneTransforms(scene);
}
public static void Initialize()