Files
2026-06-07 16:58:24 +01:00

163 lines
5.8 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
using VRC.Udon.Common.Interfaces;
namespace VRC.SDK3.ClientSim
{
/// <summary>
/// System to hold all the current initialized Udon in the scene
/// </summary>
/// <remarks>
/// Listens to Events:
/// - ClientSimOnPlayerJoinedEvent
/// - ClientSimOnPlayerLeftEvent
/// - ClientSimOnPlayerRespawnEvent
/// </remarks>
public class ClientSimUdonManager : IClientSimUdonManager, IDisposable
{
private IClientSimEventDispatcher _eventDispatcher;
private IClientSimSyncedObjectManager _syncedObjectManager;
private IClientSimUdonEventSender _udonEventSender;
private readonly ClientSimObjectCollection<UdonBehaviour> _udonBehaviours =
new ClientSimObjectCollection<UdonBehaviour>();
private bool _isReady = false;
public ClientSimUdonManager(
IClientSimEventDispatcher eventDispatcher,
IClientSimSyncedObjectManager syncedObjectManager,
IClientSimUdonEventSender udonEventSender)
{
_eventDispatcher = eventDispatcher;
_syncedObjectManager = syncedObjectManager;
_udonEventSender = udonEventSender;
Subscribe();
}
~ClientSimUdonManager()
{
Dispose();
}
private void Subscribe()
{
_eventDispatcher.Subscribe<ClientSimOnPlayerJoinedEvent>(OnPlayerJoined);
_eventDispatcher.Subscribe<ClientSimOnPlayerLeftEvent>(OnPlayerLeft);
_eventDispatcher.Subscribe<ClientSimOnPlayerRespawnEvent>(OnPlayerRespawn);
_eventDispatcher.Subscribe<ClientSimScreenUpdateEvent>(OnScreenUpdate);
_eventDispatcher.Subscribe<ClientSimOnVRCPlusMassGift>(OnVRCPlusMassGift);
}
public void Dispose()
{
_eventDispatcher.Unsubscribe<ClientSimOnPlayerJoinedEvent>(OnPlayerJoined);
_eventDispatcher.Unsubscribe<ClientSimOnPlayerLeftEvent>(OnPlayerLeft);
_eventDispatcher.Unsubscribe<ClientSimOnPlayerRespawnEvent>(OnPlayerRespawn);
_eventDispatcher.Unsubscribe<ClientSimScreenUpdateEvent>(OnScreenUpdate);
_eventDispatcher.Unsubscribe<ClientSimOnVRCPlusMassGift>(OnVRCPlusMassGift);
}
public void InitUdon(UdonBehaviour behaviour, IUdonProgram program)
{
ClientSimUdonHelper[] helpers = behaviour.gameObject.GetComponents<ClientSimUdonHelper>();
foreach (ClientSimUdonHelper helper in helpers)
{
if(helper.GetUdonBehaviour() == behaviour)
{
return;
}
}
ClientSimUdonHelper helperAdded = behaviour.gameObject.AddComponent<ClientSimUdonHelper>();
helperAdded.Initialize(behaviour, this, _syncedObjectManager, _isReady);
}
public IEnumerator OnClientSimReady()
{
_isReady = true;
_udonBehaviours.ProcessAddedAndRemovedObjects();
HashSet<GameObject> objs = new HashSet<GameObject>();
foreach (var udonBehavior in _udonBehaviours.GetObjects())
{
if (udonBehavior == null || objs.Contains(udonBehavior.gameObject))
{
continue;
}
objs.Add(udonBehavior.gameObject);
foreach (var helper in udonBehavior.GetComponents<ClientSimUdonHelper>())
{
try
{
helper.OnReady();
}
catch (Exception e)
{
this.LogError($"{e.Message}\n{e.StackTrace}");
this.LogWarning($"Failed to set ready for object: {Tools.GetGameObjectPath(helper.gameObject)}");
}
}
}
// Wait one frame for all active UdonBehaviours to properly run start.
yield return null;
}
#region ClientSimEvent handling
private void OnPlayerJoined(ClientSimOnPlayerJoinedEvent joinEvent)
{
_udonEventSender.RunEvent(UdonManager.UDON_EVENT_ONINPUTMETHODCHANGED, ("inputMethod", VRCInputMethod.Keyboard));
_udonEventSender.RunEvent(UdonManager.UDON_EVENT_ONLANGUAGECHANGED, ("language", ClientSimSettings.Instance.currentLanguage));
_udonEventSender.RunEvent("_onPlayerJoined", ("player", joinEvent.player));
}
private void OnPlayerLeft(ClientSimOnPlayerLeftEvent leftEvent)
{
_udonEventSender.RunEvent("_onPlayerLeft", ("player", leftEvent.player));
}
private void OnPlayerRespawn(ClientSimOnPlayerRespawnEvent respawnEvent)
{
_udonEventSender.RunEvent("_onPlayerRespawn", ("player", respawnEvent.player));
}
private void OnScreenUpdate(ClientSimScreenUpdateEvent screenUpdateEvent)
{
_udonEventSender.RunEvent(UdonManager.UDON_EVENT_ONSCREENUPDATE, ("data", screenUpdateEvent.data));
}
private void OnVRCPlusMassGift(ClientSimOnVRCPlusMassGift giftEvent)
{
_udonEventSender.RunEvent(UdonManager.UDON_EVENT_ONVRCPLUSMASSGIFT,
("gifter", giftEvent.gifter),
("numGifts", giftEvent.numGifts));
}
#endregion
#region IClientSimUdonManager
public void AddUdonBehaviour(UdonBehaviour udonBehaviour)
{
_udonBehaviours.AddObject(udonBehaviour);
}
public void RemoveUdonBehaviour(UdonBehaviour udonBehaviour)
{
_udonBehaviours.RemoveObject(udonBehaviour);
}
#endregion
}
}