Files
2026-06-01 17:19:55 +02:00

276 lines
7.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using BlockSpace.Worlds;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
[DisallowMultipleComponent]
public sealed class NodeGraphPhotonSync : MonoBehaviourPunCallbacks
{
[Serializable]
private sealed class NodeRecordEnvelope
{
public WorldGroupsCodec.WorldNodeRecord record;
}
[SerializeField]
private NodeGraphManager nodeGraphManager;
[SerializeField]
private float lateJoinReplayDelay = 0.5f;
private PhotonView cachedPhotonView;
private void Reset()
{
nodeGraphManager = GetComponent<NodeGraphManager>();
}
private void Awake()
{
cachedPhotonView = GetComponent<PhotonView>();
if (nodeGraphManager == null)
{
nodeGraphManager = GetComponent<NodeGraphManager>();
if (nodeGraphManager == null)
{
nodeGraphManager = UnityEngine.Object.FindAnyObjectByType<NodeGraphManager>();
}
}
nodeGraphManager?.RegisterNetworkSync(this);
}
public override void OnEnable()
{
base.OnEnable();
nodeGraphManager?.RegisterNetworkSync(this);
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
if (!(nodeGraphManager == null) && !PhotonNetwork.IsMasterClient)
{
nodeGraphManager.ClearAllNodesForNetworkSync();
}
}
public override void OnPlayerEnteredRoom(Player newPlayer)
{
base.OnPlayerEnteredRoom(newPlayer);
if (newPlayer != null)
{
nodeGraphManager?.NotifyPlayerJoined(newPlayer.ActorNumber);
}
if (PhotonNetwork.IsMasterClient && newPlayer != null && !(nodeGraphManager == null))
{
StartCoroutine(SendExistingGraphToPlayerAfterDelay(newPlayer));
}
}
public override void OnPlayerLeftRoom(Player otherPlayer)
{
base.OnPlayerLeftRoom(otherPlayer);
if (otherPlayer != null)
{
nodeGraphManager?.NotifyPlayerLeft(otherPlayer.ActorNumber);
}
}
public override void OnLeftRoom()
{
int num = ((PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0);
if (num > 0)
{
nodeGraphManager?.NotifyPlayerLeft(num);
}
base.OnLeftRoom();
}
public void BroadcastUpsertNode(Node node, Player targetPlayer = null)
{
if (!(node == null) && CanSendRpc())
{
WorldGroupsCodec.WorldNodeRecord record = nodeGraphManager.BuildNetworkNodeRecord(node);
BroadcastUpsertRecord(record, targetPlayer);
}
}
public void BroadcastDeleteNode(int nodeId)
{
if (CanSendRpc() && nodeId > 0)
{
cachedPhotonView.RPC("RPC_DeleteNode", RpcTarget.Others, nodeId);
}
}
public void BroadcastConnectWire(WorldGroupsCodec.WorldWireRecord record, Player targetPlayer = null)
{
int groupId;
bool flag = WorldGroupsCodec.TryGetGroupRuntimeWireSourceId(record, out groupId) || WorldGroupsCodec.TryGetGroupSavedWireIndex(record, out groupId);
if (CanSendRpc() && record.inputNodeId > 0 && !string.IsNullOrEmpty(record.inputPortName) && (flag || record.outputNodeId > 0))
{
if (targetPlayer != null)
{
cachedPhotonView.RPC("RPC_ConnectWire", targetPlayer, record.outputNodeId, record.outputPortName, record.inputNodeId, record.inputPortName);
}
else
{
cachedPhotonView.RPC("RPC_ConnectWire", RpcTarget.Others, record.outputNodeId, record.outputPortName, record.inputNodeId, record.inputPortName);
}
}
}
public void BroadcastDisconnectInput(int inputNodeId, string inputPortName)
{
if (CanSendRpc() && inputNodeId > 0 && !string.IsNullOrEmpty(inputPortName))
{
cachedPhotonView.RPC("RPC_DisconnectInput", RpcTarget.Others, inputNodeId, inputPortName);
}
}
public void BroadcastDisconnectOutput(int outputNodeId, string outputPortName)
{
if (CanSendRpc() && outputNodeId > 0 && !string.IsNullOrEmpty(outputPortName))
{
cachedPhotonView.RPC("RPC_DisconnectOutput", RpcTarget.Others, outputNodeId, outputPortName);
}
}
public void BroadcastTriggerRun(int outputNodeId, string outputPortName)
{
if (CanSendRpc() && outputNodeId > 0 && !string.IsNullOrEmpty(outputPortName))
{
cachedPhotonView.RPC("RPC_TriggerRun", RpcTarget.Others, outputNodeId, outputPortName);
}
}
public void BroadcastEventRun(int nodeId, string outputPortName)
{
if (CanSendRpc() && nodeId > 0 && !string.IsNullOrEmpty(outputPortName))
{
cachedPhotonView.RPC("RPC_EventRun", RpcTarget.Others, nodeId, outputPortName);
}
}
[PunRPC]
private void RPC_UpsertNode(string recordJson)
{
if (!(nodeGraphManager == null) && !string.IsNullOrEmpty(recordJson))
{
NodeRecordEnvelope nodeRecordEnvelope = JsonUtility.FromJson<NodeRecordEnvelope>(recordJson);
if (nodeRecordEnvelope != null)
{
nodeGraphManager.ApplyNetworkNodeRecord(nodeRecordEnvelope.record);
}
}
}
[PunRPC]
private void RPC_DeleteNode(int nodeId)
{
nodeGraphManager?.ApplyNetworkDelete(nodeId);
}
[PunRPC]
private void RPC_ConnectWire(int outputNodeId, string outputPortName, int inputNodeId, string inputPortName)
{
if (!(nodeGraphManager == null))
{
nodeGraphManager.ApplyNetworkWireRecord(new WorldGroupsCodec.WorldWireRecord
{
outputNodeId = outputNodeId,
outputPortName = outputPortName,
inputNodeId = inputNodeId,
inputPortName = inputPortName
});
}
}
[PunRPC]
private void RPC_DisconnectInput(int inputNodeId, string inputPortName)
{
nodeGraphManager?.ApplyNetworkDisconnectInput(inputNodeId, inputPortName);
}
[PunRPC]
private void RPC_DisconnectOutput(int outputNodeId, string outputPortName)
{
nodeGraphManager?.ApplyNetworkDisconnectOutput(outputNodeId, outputPortName);
}
[PunRPC]
private void RPC_TriggerRun(int outputNodeId, string outputPortName)
{
nodeGraphManager?.ApplyNetworkTriggerRun(outputNodeId, outputPortName);
}
[PunRPC]
private void RPC_EventRun(int nodeId, string outputPortName)
{
nodeGraphManager?.ApplyNetworkTriggerRun(nodeId, outputPortName);
}
private IEnumerator SendExistingGraphToPlayerAfterDelay(Player newPlayer)
{
float num = Mathf.Max(0f, lateJoinReplayDelay);
if (num > 0f)
{
yield return new WaitForSecondsRealtime(num);
}
else
{
yield return null;
}
if (PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient && newPlayer != null && !(nodeGraphManager == null))
{
List<Node> allNodesSnapshot = nodeGraphManager.GetAllNodesSnapshot();
for (int i = 0; i < allNodesSnapshot.Count; i++)
{
BroadcastUpsertNode(allNodesSnapshot[i], newPlayer);
}
yield return null;
List<WorldGroupsCodec.WorldWireRecord> list = nodeGraphManager.BuildWorldWireRecords();
for (int j = 0; j < list.Count; j++)
{
BroadcastConnectWire(list[j], newPlayer);
}
}
}
private void BroadcastUpsertRecord(WorldGroupsCodec.WorldNodeRecord record, Player targetPlayer)
{
if (CanSendRpc())
{
string text = JsonUtility.ToJson(new NodeRecordEnvelope
{
record = record
});
if (targetPlayer != null)
{
cachedPhotonView.RPC("RPC_UpsertNode", targetPlayer, text);
}
else
{
cachedPhotonView.RPC("RPC_UpsertNode", RpcTarget.Others, text);
}
}
}
private bool CanSendRpc()
{
if (!PhotonNetwork.InRoom || cachedPhotonView == null)
{
return false;
}
if (cachedPhotonView.ViewID == 0)
{
Debug.LogWarning("NodeGraphPhotonSync requires a valid PhotonView ViewID to send RPCs.", this);
return false;
}
return true;
}
}