using System;
using System.Collections.Generic;
using UnityEngine;
namespace Unity.Netcode.RuntimeTests
{
///
/// Used in conjunction with the RpcQueueTest to validate:
/// - Sending and Receiving pipeline to validate that both sending and receiving pipelines are functioning properly.
/// - Usage of the ServerRpcParams.Send.UpdateStage and ClientRpcParams.Send.UpdateStage functionality.
/// - Rpcs receive will be invoked at the appropriate NetworkUpdateStage.
///
public class RpcPipelineTestComponent : NetworkBehaviour
{
///
/// Allows the external RPCQueueTest to begin testing or stop it
///
public bool PingSelfEnabled;
///
/// How many times will we iterate through the various NetworkUpdateStage values?
/// (defaults to 2)
///
public int MaxIterations = 2;
// Start is called before the first frame update
private void Start()
{
m_MaxStagesSent = Enum.GetValues(typeof(NetworkUpdateStage)).Length * MaxIterations;
//Start out with this being true (for first sequence)
m_ClientReceivedRpc = true;
}
///
/// Determine if we have iterated over more than our maximum stages we want to test
///
/// true or false (did we exceed the max iterations or not?)
public bool ExceededMaxIterations()
{
if (m_StagesSent.Count > m_MaxStagesSent && m_MaxStagesSent > 0)
{
return true;
}
return false;
}
///
/// Returns back whether the test has completed the total number of iterations
///
///
public bool IsTestComplete()
{
if (m_Counter >= MaxIterations)
{
return true;
}
return false;
}
private bool m_ClientReceivedRpc;
private int m_Counter = 0;
private int m_MaxStagesSent = 0;
private ServerRpcParams m_ServerParams;
private ClientRpcParams m_ClientParams;
private NetworkUpdateStage m_LastUpdateStage;
// Update is called once per frame
private void Update()
{
if (NetworkManager.Singleton.IsListening && PingSelfEnabled && m_ClientReceivedRpc)
{
//Reset this for the next sequence of rpcs
m_ClientReceivedRpc = false;
//As long as testing isn't completed, keep testing
if (!IsTestComplete())
{
PingMySelfServerRpc(m_StagesSent.Count, m_ServerParams);
}
}
}
private readonly List m_ServerStagesReceived = new List();
private readonly List m_ClientStagesReceived = new List();
private readonly List m_StagesSent = new List();
///
/// Assures all update stages were in alginment with one another
///
/// true or false
public bool ValidateUpdateStages()
{
var validated = false;
if (m_ServerStagesReceived.Count == m_ClientStagesReceived.Count && m_ClientStagesReceived.Count == m_StagesSent.Count)
{
for (int i = 0; i < m_StagesSent.Count; i++)
{
var currentStage = m_StagesSent[i];
if (m_ServerStagesReceived[i] != currentStage)
{
Debug.Log($"ServerRpc Update Stage ({m_ServerStagesReceived[i]}) is not equal to the current update stage ({currentStage})");
return validated;
}
if (m_ClientStagesReceived[i] != currentStage)
{
Debug.Log($"ClientRpc Update Stage ({m_ClientStagesReceived[i]}) is not equal to the current update stage ({currentStage})");
return validated;
}
}
validated = true;
}
return validated;
}
///
/// Server side RPC for testing
///
/// server rpc parameters
[ServerRpc]
private void PingMySelfServerRpc(int currentCount, ServerRpcParams parameters = default)
{
Debug.Log($"{nameof(PingMySelfServerRpc)}: [HostClient][ServerRpc][{currentCount}] invoked.");
PingMySelfClientRpc(currentCount, m_ClientParams);
}
///
/// Client Side RPC called by PingMySelfServerRPC to validate both Client->Server and Server-Client pipeline is working
///
/// client rpc parameters
[ClientRpc]
private void PingMySelfClientRpc(int currentCount, ClientRpcParams parameters = default)
{
Debug.Log($"{nameof(PingMySelfClientRpc)}: [HostServer][ClientRpc][{currentCount}] invoked. (previous output line should confirm this)");
m_ClientReceivedRpc = true;
}
}
}