Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Commit

Permalink
Fixes to handling iterating over synced objects and udon objects to p…
Browse files Browse the repository at this point in the history
…revent exceptions. This mainly happened when an object was spawned at start or player joined. (Thank you GotoFinal for informing me of the bug)
  • Loading branch information
CyanLaser committed Mar 17, 2021
1 parent e53d01f commit ceaf4be
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 15 deletions.
61 changes: 54 additions & 7 deletions CyanEmu/Scripts/CyanEmuMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,9 @@ private IEnumerator OnNetworkReady()

SpawnLocalPlayer();
}

yield return new WaitForSeconds(0.1f);

networkReady_ = true;

yield return new WaitForSeconds(0.1f);
CyanEmuPlayerManager.OnNetworkReady();
}

Expand Down Expand Up @@ -411,7 +410,7 @@ private void OnPlayerLeft(VRCPlayerApi player)
int masterID = CyanEmuPlayerManager.GetMasterID();
VRCPlayerApi masterPlayer = VRCPlayerApi.GetPlayerById(masterID);

foreach (CyanEmuSyncedObjectHelper sync in allSyncedObjects_)
foreach (CyanEmuSyncedObjectHelper sync in GetAllSyncedObjects())
{
GameObject syncObj = sync.gameObject;
if (Networking.GetOwner(syncObj)?.playerId == player.playerId)
Expand Down Expand Up @@ -468,8 +467,16 @@ private void LateUpdate()
playerController_.Teleport(descriptor_.spawns[0], false);
}

bool containsNull = false;
List<GameObject> objsToDestroy = new List<GameObject>();
foreach (CyanEmuSyncedObjectHelper sync in allSyncedObjects_)
{
if (sync == null)
{
containsNull = true;
continue;
}

if (!sync.SyncPosition)
{
continue;
Expand All @@ -483,15 +490,25 @@ private void LateUpdate()
}
else
{
Destroy(sync.gameObject);
objsToDestroy.Add(sync.gameObject);
}
}
}

foreach (var obj in objsToDestroy)
{
Destroy(obj);
}

if (containsNull)
{
GetAllSyncedObjects();
}
}

public static void AddSyncedObject(CyanEmuSyncedObjectHelper sync)
{
if (instance_ == null)
if (instance_ == null || sync == null)
{
return;
}
Expand All @@ -506,7 +523,37 @@ public static void RemoveSyncedObject(CyanEmuSyncedObjectHelper sync)
return;
}

instance_.allSyncedObjects_.Remove(sync);
if (sync == null)
{
instance_.GetAllSyncedObjects();
}
else
{
instance_.allSyncedObjects_.Remove(sync);
}
}

// Will get all non null syncs. Will also remove null if contained in the list.
private List<CyanEmuSyncedObjectHelper> GetAllSyncedObjects()
{
List<CyanEmuSyncedObjectHelper> curSyncs = new List<CyanEmuSyncedObjectHelper>();
bool containsNull = false;
foreach (var sync in allSyncedObjects_)
{
if (sync == null)
{
containsNull = true;
continue;
}
curSyncs.Add(sync);
}

if (containsNull)
{
allSyncedObjects_ = new HashSet<CyanEmuSyncedObjectHelper>(curSyncs);
}

return curSyncs;
}
}
}
16 changes: 12 additions & 4 deletions CyanEmu/Scripts/VRCSDK3/CyanEmuUdonHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ namespace VRCPrefabs.CyanEmu
[AddComponentMenu("")]
public class CyanEmuUdonHelper : CyanEmuSyncedObjectHelper, ICyanEmuInteractable, ICyanEmuPickupable, ICyanEmuStationHandler, ICyanEmuSyncableHandler
{
private UdonBehaviour udonbehaviour_;

// VRCSDK3-2021.01.28.19.07 modified the name of the _isNetworkReady variable to _isReady.
// Check both for backwards compatibility so I don't require users to update their old sdks.
private static FieldInfo isNetworkReady_ =
Expand All @@ -21,11 +19,13 @@ public class CyanEmuUdonHelper : CyanEmuSyncedObjectHelper, ICyanEmuInteractable
typeof(UdonBehaviour).GetField("_isReady", (BindingFlags.Instance | BindingFlags.NonPublic));

private static FieldInfo NetworkReadyFieldInfo_ => isNetworkReady_ ?? isReady_;

private UdonBehaviour udonbehaviour_;

public static void OnInit(UdonBehaviour behaviour, IUdonProgram program)
{
CyanEmuUdonHelper helper = behaviour.gameObject.AddComponent<CyanEmuUdonHelper>();
helper.SetUdonbehaviour(behaviour);
helper.SetUdonBehaviour(behaviour);

NetworkReadyFieldInfo_.SetValue(behaviour, CyanEmuMain.IsNetworkReady());
}
Expand All @@ -35,6 +35,14 @@ public void OnNetworkReady()
NetworkReadyFieldInfo_.SetValue(udonbehaviour_, true);
}

private void Start()
{
if (udonbehaviour_ == null)
{
DestroyImmediate(this);
}
}

public static void SendCustomNetworkEventHook(UdonBehaviour behaviour, NetworkEventTarget target, string eventName)
{
if (target == NetworkEventTarget.All || (target == NetworkEventTarget.Owner && Networking.IsOwner(behaviour.gameObject)))
Expand All @@ -48,7 +56,7 @@ public static void SendCustomNetworkEventHook(UdonBehaviour behaviour, NetworkEv
}
}

private void SetUdonbehaviour(UdonBehaviour udonbehaviour)
private void SetUdonBehaviour(UdonBehaviour udonbehaviour)
{
if (udonbehaviour == null)
{
Expand Down
28 changes: 24 additions & 4 deletions CyanEmu/Scripts/VRCSDK3/CyanEmuUdonManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ private void AddObjectAndChildrenToBlackList(Transform obj, UdonManager udonMana
public void OnNetworkReady()
{
HashSet<GameObject> objs = new HashSet<GameObject>();
foreach (var udonBehavior in allUdonBehaviours_)
List<UdonBehaviour> currentUdon = new List<UdonBehaviour>(allUdonBehaviours_);
foreach (var udonBehavior in currentUdon)
{
if (udonBehavior == null || objs.Contains(udonBehavior.gameObject))
{
Expand All @@ -76,30 +77,49 @@ public void OnPlayerJoined(VRCPlayerApi player)
{
AddObjectAndChildrenToBlackList(player.gameObject.transform, UdonManager.Instance);

foreach (var udonBehavior in allUdonBehaviours_)
List<UdonBehaviour> currentUdon = new List<UdonBehaviour>(allUdonBehaviours_);
foreach (var udonBehavior in currentUdon)
{
if (udonBehavior == null)
{
Debug.Log("Null behaviour OnPlayerJoined");
continue;
}
udonBehavior.RunEvent("_onPlayerJoined", ("player", player));
}
}

public void OnPlayerLeft(VRCPlayerApi player)
{
foreach (var udonBehavior in allUdonBehaviours_)
List<UdonBehaviour> currentUdon = new List<UdonBehaviour>(allUdonBehaviours_);
foreach (var udonBehavior in currentUdon)
{
if (udonBehavior == null)
{
Debug.Log("Null behaviour OnPlayerLeft");
continue;
}
udonBehavior.RunEvent("_onPlayerLeft", ("player", player));
}
}

public void OnPlayerRespawn(VRCPlayerApi player)
{
foreach (var udonBehavior in allUdonBehaviours_)
List<UdonBehaviour> currentUdon = new List<UdonBehaviour>(allUdonBehaviours_);
foreach (var udonBehavior in currentUdon)
{
if (udonBehavior == null)
{
Debug.Log("Null behaviour OnPlayerRespawn");
continue;
}
udonBehavior.RunEvent("_onPlayerRespawn", ("player", player));
}
}

public void OnSpawnedObject(GameObject spawnedObject)
{
// TODO fix this
UdonBehaviour[] udonBehaviours = spawnedObject.GetComponentsInChildren<UdonBehaviour>();
foreach (var udonBehaviour in udonBehaviours)
{
Expand Down

0 comments on commit ceaf4be

Please sign in to comment.