This commit is contained in:
Mister_Nebula 2020-12-02 12:42:26 +00:00
parent b649090258
commit 799b2d60db
22 changed files with 5966 additions and 70 deletions

View File

@ -72,9 +72,9 @@ namespace QSB.Animation
WriteParameters(m_ParameterWriter, false);
animationMessage.parameters = m_ParameterWriter.ToArray();
if (HasAuthority || ClientScene.readyConnection != null)
if (HasAuthority || QSBClientScene.readyConnection != null)
{
ClientScene.readyConnection.Send(40, animationMessage);
QSBClientScene.readyConnection.Send(40, animationMessage);
}
else
{
@ -130,9 +130,9 @@ namespace QSB.Animation
m_ParameterWriter.SeekZero();
WriteParameters(m_ParameterWriter, true);
parametersMessage.parameters = m_ParameterWriter.ToArray();
if (HasAuthority && ClientScene.readyConnection != null)
if (HasAuthority && QSBClientScene.readyConnection != null)
{
ClientScene.readyConnection.Send(41, parametersMessage);
QSBClientScene.readyConnection.Send(41, parametersMessage);
}
else
{
@ -274,7 +274,7 @@ namespace QSB.Animation
{
return;
}
var readyConnection = ClientScene.readyConnection;
var readyConnection = QSBClientScene.readyConnection;
if (readyConnection == null)
{
return;
@ -291,7 +291,7 @@ namespace QSB.Animation
}
}
internal static void OnAnimationServerMessage(NetworkMessage netMsg)
internal static void OnAnimationServerMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage(AnimationMessage);
var localObject = NetworkServer.FindLocalObject(AnimationMessage.netId);
@ -305,7 +305,7 @@ namespace QSB.Animation
NetworkServer.SendToReady(localObject, 40, AnimationMessage);
}
internal static void OnAnimationParametersServerMessage(NetworkMessage netMsg)
internal static void OnAnimationParametersServerMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage(ParametersMessage);
var localObject = NetworkServer.FindLocalObject(ParametersMessage.netId);
@ -319,7 +319,7 @@ namespace QSB.Animation
NetworkServer.SendToReady(localObject, 41, ParametersMessage);
}
internal static void OnAnimationTriggerServerMessage(NetworkMessage netMsg)
internal static void OnAnimationTriggerServerMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage(TriggersMessage);
var localObject = NetworkServer.FindLocalObject(TriggersMessage.netId);
@ -332,10 +332,10 @@ namespace QSB.Animation
NetworkServer.SendToReady(localObject, 42, TriggersMessage);
}
internal static void OnAnimationClientMessage(NetworkMessage netMsg)
internal static void OnAnimationClientMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage(AnimationMessage);
var localObject = ClientScene.FindLocalObject(AnimationMessage.netId);
var localObject = QSBClientScene.FindLocalObject(AnimationMessage.netId);
if (localObject == null)
return;
var component = localObject.GetComponent<QSBNetworkAnimator>();
@ -345,10 +345,10 @@ namespace QSB.Animation
component.HandleAnimMsg(AnimationMessage, reader);
}
internal static void OnAnimationParametersClientMessage(NetworkMessage netMsg)
internal static void OnAnimationParametersClientMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage(ParametersMessage);
var localObject = ClientScene.FindLocalObject(ParametersMessage.netId);
var localObject = QSBClientScene.FindLocalObject(ParametersMessage.netId);
if (localObject == null)
return;
var component = localObject.GetComponent<QSBNetworkAnimator>();
@ -358,10 +358,10 @@ namespace QSB.Animation
component.HandleAnimParamsMsg(ParametersMessage, reader);
}
internal static void OnAnimationTriggerClientMessage(NetworkMessage netMsg)
internal static void OnAnimationTriggerClientMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage(TriggersMessage);
var localObject = ClientScene.FindLocalObject(TriggersMessage.netId);
var localObject = QSBClientScene.FindLocalObject(TriggersMessage.netId);
if (localObject == null)
return;
var component = localObject.GetComponent<QSBNetworkAnimator>();

View File

@ -132,6 +132,7 @@
<Compile Include="Animation\Events\QSBAnimationTriggerMessage.cs" />
<Compile Include="Animation\PlayerHeadRotationSync.cs" />
<Compile Include="Animation\QSBNetworkAnimator.cs" />
<Compile Include="QSBClientAuthorityMessage.cs" />
<Compile Include="ConversationSync\Events\ConversationEvent.cs" />
<Compile Include="ConversationSync\Events\ConversationMessage.cs" />
<Compile Include="ConversationSync\ConversationPatches.cs" />
@ -162,13 +163,29 @@
<Compile Include="Patches\QSBPatchManager.cs" />
<Compile Include="Player\Events\ServerSendPlayerStatesEvent.cs" />
<Compile Include="Player\PlayerSyncObject.cs" />
<Compile Include="QSBClientScene.cs" />
<Compile Include="QSBInputManager.cs" />
<Compile Include="QSBLocalClient.cs" />
<Compile Include="QSBNetworkBehaviour.cs" />
<Compile Include="QSBNetworkClient.cs" />
<Compile Include="QSBNetworkConnection.cs" />
<Compile Include="QSBNetworkIdentity.cs" />
<Compile Include="QSBNetworkLobby.cs" />
<Compile Include="Patches\QSBPatch.cs" />
<Compile Include="Patches\QSBPatchTypes.cs" />
<Compile Include="QSBNetworkMessage.cs" />
<Compile Include="QSBNetworkMessageDelegate.cs" />
<Compile Include="QSBNetworkMessageHandlers.cs" />
<Compile Include="QSBNetworkScene.cs" />
<Compile Include="QSBNetworkServer.cs" />
<Compile Include="QSBObjectDestroyMessage.cs" />
<Compile Include="QSBObjectSpawnFinishedMessage.cs" />
<Compile Include="QSBObjectSpawnMessage.cs" />
<Compile Include="QSBObjectSpawnSceneMessage.cs" />
<Compile Include="QSBOwnerMessage.cs" />
<Compile Include="QSBPlayerController.cs" />
<Compile Include="QSBSceneManager.cs" />
<Compile Include="QSBUtility.cs" />
<Compile Include="TimeSync\TimeSyncType.cs" />
<Compile Include="TimeSync\TimeSyncUI.cs" />
<Compile Include="TimeSync\WakeUpPatches.cs" />

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Networking;
namespace QSB
{
class QSBClientAuthorityMessage : MessageBase
{
public override void Deserialize(NetworkReader reader)
{
netId = reader.ReadNetworkId();
authority = reader.ReadBoolean();
}
public override void Serialize(NetworkWriter writer)
{
writer.Write(netId);
writer.Write(authority);
}
public NetworkInstanceId netId;
public bool authority;
}
}

952
QSB/QSBClientScene.cs Normal file
View File

@ -0,0 +1,952 @@
using QSB.Animation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;
namespace QSB
{
public class QSBClientScene
{
private static bool HasMigrationPending() => reconnectId != -1;
public static void SetReconnectId(int newReconnectId, PeerInfoMessage[] peers)
{
reconnectId = newReconnectId;
s_Peers = peers;
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::SetReconnectId: " + newReconnectId);
}
}
internal static void SetNotReady() => ready = false;
public static List<QSBPlayerController> localPlayers { get; private set; } = new List<QSBPlayerController>();
public static bool ready { get; private set; }
public static QSBNetworkConnection readyConnection { get; private set; }
public static int reconnectId { get; private set; } = -1;
public static Dictionary<NetworkInstanceId, QSBNetworkIdentity> Objects => s_NetworkScene.localObjects;
public static Dictionary<NetworkHash128, GameObject> Prefabs => QSBNetworkScene.guidToPrefab;
public static Dictionary<NetworkSceneId, QSBNetworkIdentity> SpawnableObjects { get; private set; }
internal static void Shutdown()
{
s_NetworkScene.Shutdown();
localPlayers = new List<QSBPlayerController>();
s_PendingOwnerIds = new List<PendingOwner>();
SpawnableObjects = null;
readyConnection = null;
ready = false;
s_IsSpawnFinished = false;
reconnectId = -1;
NetworkTransport.Shutdown();
NetworkTransport.Init();
}
internal static bool GetPlayerController(short playerControllerId, out QSBPlayerController player)
{
player = null;
bool result;
if ((int)playerControllerId >= localPlayers.Count)
{
if (LogFilter.logWarn)
{
Debug.Log("ClientScene::GetPlayer: no local player found for: " + playerControllerId);
}
result = false;
}
else if (localPlayers[(int)playerControllerId] == null)
{
if (LogFilter.logWarn)
{
Debug.LogWarning("ClientScene::GetPlayer: local player is null for: " + playerControllerId);
}
result = false;
}
else
{
player = localPlayers[(int)playerControllerId];
result = (player.gameObject != null);
}
return result;
}
internal static void InternalAddPlayer(QSBNetworkIdentity view, short playerControllerId)
{
if (LogFilter.logDebug)
{
Debug.LogWarning("ClientScene::InternalAddPlayer: playerControllerId : " + playerControllerId);
}
if ((int)playerControllerId >= localPlayers.Count)
{
if (LogFilter.logWarn)
{
Debug.LogWarning("ClientScene::InternalAddPlayer: playerControllerId higher than expected: " + playerControllerId);
}
while ((int)playerControllerId >= localPlayers.Count)
{
localPlayers.Add(new QSBPlayerController());
}
}
var playerController = new QSBPlayerController
{
gameObject = view.gameObject,
playerControllerId = playerControllerId,
unetView = view
};
localPlayers[(int)playerControllerId] = playerController;
readyConnection.SetPlayerController(playerController);
}
public static bool AddPlayer(short playerControllerId) => AddPlayer(null, playerControllerId);
public static bool AddPlayer(QSBNetworkConnection readyConn, short playerControllerId) => AddPlayer(readyConn, playerControllerId, null);
public static bool AddPlayer(QSBNetworkConnection readyConn, short playerControllerId, MessageBase extraMessage)
{
bool result;
if (playerControllerId < 0)
{
if (LogFilter.logError)
{
Debug.LogError("ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " is negative");
}
result = false;
}
else if (playerControllerId > 32)
{
if (LogFilter.logError)
{
Debug.LogError(string.Concat(new object[]
{
"ClientScene::AddPlayer: playerControllerId of ",
playerControllerId,
" is too high, max is ",
32
}));
}
result = false;
}
else
{
if (playerControllerId > 16)
{
if (LogFilter.logWarn)
{
Debug.LogWarning("ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " is unusually high");
}
}
while ((int)playerControllerId >= localPlayers.Count)
{
localPlayers.Add(new QSBPlayerController());
}
if (readyConn == null)
{
if (!ready)
{
if (LogFilter.logError)
{
Debug.LogError("Must call AddPlayer() with a connection the first time to become ready.");
}
return false;
}
}
else
{
ready = true;
readyConnection = readyConn;
}
if (readyConnection.GetPlayerController(playerControllerId, out var playerController))
{
if (playerController.IsValid && playerController.gameObject != null)
{
if (LogFilter.logError)
{
Debug.LogError("ClientScene::AddPlayer: playerControllerId of " + playerControllerId + " already in use.");
}
return false;
}
}
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"ClientScene::AddPlayer() for ID ",
playerControllerId,
" called with connection [",
readyConnection,
"]"
}));
}
if (!HasMigrationPending())
{
var addPlayerMessage = new AddPlayerMessage
{
playerControllerId = playerControllerId
};
if (extraMessage != null)
{
var networkWriter = new NetworkWriter();
extraMessage.Serialize(networkWriter);
addPlayerMessage.msgData = networkWriter.ToArray();
addPlayerMessage.msgSize = (int)networkWriter.Position;
}
readyConnection.Send(37, addPlayerMessage);
result = true;
}
else
{
result = SendReconnectMessage(extraMessage);
}
}
return result;
}
public static bool SendReconnectMessage(MessageBase extraMessage)
{
bool result;
if (!HasMigrationPending())
{
result = false;
}
else
{
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::AddPlayer reconnect " + reconnectId);
}
if (s_Peers == null)
{
SetReconnectId(-1, null);
if (LogFilter.logError)
{
Debug.LogError("ClientScene::AddPlayer: reconnecting, but no peers.");
}
result = false;
}
else
{
for (var i = 0; i < s_Peers.Length; i++)
{
var peerInfoMessage = s_Peers[i];
if (peerInfoMessage.playerIds != null)
{
if (peerInfoMessage.connectionId == reconnectId)
{
for (var j = 0; j < peerInfoMessage.playerIds.Length; j++)
{
var reconnectMessage = new ReconnectMessage
{
oldConnectionId = reconnectId,
netId = peerInfoMessage.playerIds[j].netId,
playerControllerId = peerInfoMessage.playerIds[j].playerControllerId
};
if (extraMessage != null)
{
var networkWriter = new NetworkWriter();
extraMessage.Serialize(networkWriter);
reconnectMessage.msgData = networkWriter.ToArray();
reconnectMessage.msgSize = (int)networkWriter.Position;
}
readyConnection.Send(47, reconnectMessage);
}
}
}
}
SetReconnectId(-1, null);
result = true;
}
}
return result;
}
public static bool RemovePlayer(short playerControllerId)
{
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"ClientScene::RemovePlayer() for ID ",
playerControllerId,
" called with connection [",
readyConnection,
"]"
}));
}
bool result;
if (readyConnection.GetPlayerController(playerControllerId, out var playerController))
{
var removePlayerMessage = new RemovePlayerMessage
{
playerControllerId = playerControllerId
};
readyConnection.Send(38, removePlayerMessage);
readyConnection.RemovePlayerController(playerControllerId);
localPlayers[(int)playerControllerId] = new QSBPlayerController();
UnityEngine.Object.Destroy(playerController.gameObject);
result = true;
}
else
{
if (LogFilter.logError)
{
Debug.LogError("Failed to find player ID " + playerControllerId);
}
result = false;
}
return result;
}
public static bool Ready(QSBNetworkConnection conn)
{
bool result;
if (ready)
{
if (LogFilter.logError)
{
Debug.LogError("A connection has already been set as ready. There can only be one.");
}
result = false;
}
else
{
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::Ready() called with connection [" + conn + "]");
}
if (conn != null)
{
var msg = new ReadyMessage();
conn.Send(35, msg);
ready = true;
readyConnection = conn;
readyConnection.isReady = true;
result = true;
}
else
{
if (LogFilter.logError)
{
Debug.LogError("Ready() called with invalid connection object: conn=null");
}
result = false;
}
}
return result;
}
public static QSBNetworkClient ConnectLocalServer()
{
var localClient = new QSBLocalClient();
QSBNetworkServer.instance.ActivateLocalClientScene();
localClient.InternalConnectLocalServer(true);
return localClient;
}
internal static QSBNetworkClient ReconnectLocalServer()
{
var localClient = new QSBLocalClient();
QSBNetworkServer.instance.ActivateLocalClientScene();
localClient.InternalConnectLocalServer(false);
return localClient;
}
internal static void ClearLocalPlayers() => localPlayers.Clear();
internal static void HandleClientDisconnect(QSBNetworkConnection conn)
{
if (readyConnection == conn && ready)
{
ready = false;
readyConnection = null;
}
}
internal static void PrepareToSpawnSceneObjects()
{
SpawnableObjects = new Dictionary<NetworkSceneId, QSBNetworkIdentity>();
foreach (var networkIdentity in Resources.FindObjectsOfTypeAll<QSBNetworkIdentity>())
{
if (!networkIdentity.gameObject.activeSelf)
{
if (networkIdentity.gameObject.hideFlags != HideFlags.NotEditable && networkIdentity.gameObject.hideFlags != HideFlags.HideAndDontSave)
{
if (!networkIdentity.SceneId.IsEmpty())
{
SpawnableObjects[networkIdentity.SceneId] = networkIdentity;
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::PrepareSpawnObjects sceneId:" + networkIdentity.SceneId);
}
}
}
}
}
}
internal static QSBNetworkIdentity SpawnSceneObject(NetworkSceneId sceneId)
{
QSBNetworkIdentity result;
if (SpawnableObjects.ContainsKey(sceneId))
{
var networkIdentity = SpawnableObjects[sceneId];
SpawnableObjects.Remove(sceneId);
result = networkIdentity;
}
else
{
result = null;
}
return result;
}
internal static void RegisterSystemHandlers(QSBNetworkClient client, bool localClient)
{
if (localClient)
{
client.RegisterHandlerSafe((short)1, new QSBNetworkMessageDelegate(OnLocalClientObjectDestroy));
client.RegisterHandlerSafe((short)13, new QSBNetworkMessageDelegate(OnLocalClientObjectHide));
client.RegisterHandlerSafe((short)3, new QSBNetworkMessageDelegate(OnLocalClientObjectSpawn));
client.RegisterHandlerSafe((short)10, new QSBNetworkMessageDelegate(OnLocalClientObjectSpawnScene));
client.RegisterHandlerSafe((short)15, new QSBNetworkMessageDelegate(OnClientAuthority));
}
else
{
client.RegisterHandlerSafe((short)3, new QSBNetworkMessageDelegate(OnObjectSpawn));
client.RegisterHandlerSafe((short)10, new QSBNetworkMessageDelegate(OnObjectSpawnScene));
client.RegisterHandlerSafe((short)12, new QSBNetworkMessageDelegate(OnObjectSpawnFinished));
client.RegisterHandlerSafe((short)1, new QSBNetworkMessageDelegate(OnObjectDestroy));
client.RegisterHandlerSafe((short)13, new QSBNetworkMessageDelegate(OnObjectDestroy));
client.RegisterHandlerSafe((short)8, new QSBNetworkMessageDelegate(OnUpdateVarsMessage));
client.RegisterHandlerSafe((short)4, new QSBNetworkMessageDelegate(OnOwnerMessage));
client.RegisterHandlerSafe((short)9, new QSBNetworkMessageDelegate(OnSyncListMessage));
client.RegisterHandlerSafe((short)40, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationClientMessage));
client.RegisterHandlerSafe((short)41, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationParametersClientMessage));
client.RegisterHandlerSafe((short)15, new QSBNetworkMessageDelegate(OnClientAuthority));
}
client.RegisterHandlerSafe((short)2, new QSBNetworkMessageDelegate(OnRPCMessage));
client.RegisterHandlerSafe((short)7, new QSBNetworkMessageDelegate(OnSyncEventMessage));
client.RegisterHandlerSafe((short)42, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationTriggerClientMessage));
}
internal static string GetStringForAssetId(NetworkHash128 assetId)
{
string result;
if (QSBNetworkScene.GetPrefab(assetId, out var gameObject))
{
result = gameObject.name;
}
else if (QSBNetworkScene.GetSpawnHandler(assetId, out var func))
{
result = func.GetMethodName();
}
else
{
result = "unknown";
}
return result;
}
public static void RegisterPrefab(GameObject prefab, NetworkHash128 newAssetId) => QSBNetworkScene.RegisterPrefab(prefab, newAssetId);
public static void RegisterPrefab(GameObject prefab) => QSBNetworkScene.RegisterPrefab(prefab);
public static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) => QSBNetworkScene.RegisterPrefab(prefab, spawnHandler, unspawnHandler);
public static void UnregisterPrefab(GameObject prefab) => QSBNetworkScene.UnregisterPrefab(prefab);
public static void RegisterSpawnHandler(NetworkHash128 assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler) => QSBNetworkScene.RegisterSpawnHandler(assetId, spawnHandler, unspawnHandler);
public static void UnregisterSpawnHandler(NetworkHash128 assetId) => QSBNetworkScene.UnregisterSpawnHandler(assetId);
public static void ClearSpawners() => QSBNetworkScene.ClearSpawners();
public static void DestroyAllClientObjects() => s_NetworkScene.DestroyAllClientObjects();
public static void SetLocalObject(NetworkInstanceId netId, GameObject obj) => s_NetworkScene.SetLocalObject(netId, obj, s_IsSpawnFinished, false);
public static GameObject FindLocalObject(NetworkInstanceId netId) => s_NetworkScene.FindLocalObject(netId);
private static void ApplySpawnPayload(QSBNetworkIdentity uv, Vector3 position, byte[] payload, NetworkInstanceId netId, GameObject newGameObject)
{
if (!uv.gameObject.activeSelf)
{
uv.gameObject.SetActive(true);
}
uv.transform.position = position;
if (payload != null && payload.Length > 0)
{
var reader = new NetworkReader(payload);
uv.OnUpdateVars(reader, true);
}
if (!(newGameObject == null))
{
newGameObject.SetActive(true);
uv.SetNetworkInstanceId(netId);
SetLocalObject(netId, newGameObject);
if (s_IsSpawnFinished)
{
uv.OnStartClient();
CheckForOwner(uv);
}
}
}
private static void OnObjectSpawn(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectSpawnMessage>(s_ObjectSpawnMessage);
if (!s_ObjectSpawnMessage.assetId.IsValid())
{
if (LogFilter.logError)
{
Debug.LogError("OnObjSpawn netId: " + s_ObjectSpawnMessage.netId + " has invalid asset Id");
}
}
else
{
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Client spawn handler instantiating [netId:",
s_ObjectSpawnMessage.netId,
" asset ID:",
s_ObjectSpawnMessage.assetId,
" pos:",
s_ObjectSpawnMessage.position,
"]"
}));
}
if (s_NetworkScene.GetNetworkIdentity(s_ObjectSpawnMessage.netId, out var component))
{
ApplySpawnPayload(component, s_ObjectSpawnMessage.position, s_ObjectSpawnMessage.payload, s_ObjectSpawnMessage.netId, null);
}
else if (QSBNetworkScene.GetPrefab(s_ObjectSpawnMessage.assetId, out var original))
{
GameObject gameObject = UnityEngine.Object.Instantiate<GameObject>(original, s_ObjectSpawnMessage.position, s_ObjectSpawnMessage.rotation);
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Client spawn handler instantiating [netId:",
s_ObjectSpawnMessage.netId,
" asset ID:",
s_ObjectSpawnMessage.assetId,
" pos:",
s_ObjectSpawnMessage.position,
" rotation: ",
s_ObjectSpawnMessage.rotation,
"]"
}));
}
component = gameObject.GetComponent<QSBNetworkIdentity>();
if (component == null)
{
if (LogFilter.logError)
{
Debug.LogError("Client object spawned for " + s_ObjectSpawnMessage.assetId + " does not have a NetworkIdentity");
}
}
else
{
component.Reset();
ApplySpawnPayload(component, s_ObjectSpawnMessage.position, s_ObjectSpawnMessage.payload, s_ObjectSpawnMessage.netId, gameObject);
}
}
else if (QSBNetworkScene.GetSpawnHandler(s_ObjectSpawnMessage.assetId, out var spawnDelegate))
{
var gameObject2 = spawnDelegate(s_ObjectSpawnMessage.position, s_ObjectSpawnMessage.assetId);
if (gameObject2 == null)
{
if (LogFilter.logWarn)
{
Debug.LogWarning("Client spawn handler for " + s_ObjectSpawnMessage.assetId + " returned null");
}
}
else
{
component = gameObject2.GetComponent<QSBNetworkIdentity>();
if (component == null)
{
if (LogFilter.logError)
{
Debug.LogError("Client object spawned for " + s_ObjectSpawnMessage.assetId + " does not have a network identity");
}
}
else
{
component.Reset();
component.SetDynamicAssetId(s_ObjectSpawnMessage.assetId);
ApplySpawnPayload(component, s_ObjectSpawnMessage.position, s_ObjectSpawnMessage.payload, s_ObjectSpawnMessage.netId, gameObject2);
}
}
}
else if (LogFilter.logError)
{
Debug.LogError(string.Concat(new object[]
{
"Failed to spawn server object, did you forget to add it to the NetworkManager? assetId=",
s_ObjectSpawnMessage.assetId,
" netId=",
s_ObjectSpawnMessage.netId
}));
}
}
}
private static void OnObjectSpawnScene(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectSpawnSceneMessage>(s_ObjectSpawnSceneMessage);
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Client spawn scene handler instantiating [netId:",
s_ObjectSpawnSceneMessage.netId,
" sceneId:",
s_ObjectSpawnSceneMessage.sceneId,
" pos:",
s_ObjectSpawnSceneMessage.position
}));
}
if (s_NetworkScene.GetNetworkIdentity(s_ObjectSpawnSceneMessage.netId, out var networkIdentity))
{
ApplySpawnPayload(networkIdentity, s_ObjectSpawnSceneMessage.position, s_ObjectSpawnSceneMessage.payload, s_ObjectSpawnSceneMessage.netId, networkIdentity.gameObject);
}
else
{
var networkIdentity2 = SpawnSceneObject(s_ObjectSpawnSceneMessage.sceneId);
if (networkIdentity2 == null)
{
if (LogFilter.logError)
{
Debug.LogError("Spawn scene object not found for " + s_ObjectSpawnSceneMessage.sceneId);
}
}
else
{
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Client spawn for [netId:",
s_ObjectSpawnSceneMessage.netId,
"] [sceneId:",
s_ObjectSpawnSceneMessage.sceneId,
"] obj:",
networkIdentity2.gameObject.name
}));
}
ApplySpawnPayload(networkIdentity2, s_ObjectSpawnSceneMessage.position, s_ObjectSpawnSceneMessage.payload, s_ObjectSpawnSceneMessage.netId, networkIdentity2.gameObject);
}
}
}
private static void OnObjectSpawnFinished(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectSpawnFinishedMessage>(s_ObjectSpawnFinishedMessage);
if (LogFilter.logDebug)
{
Debug.Log("SpawnFinished:" + s_ObjectSpawnFinishedMessage.state);
}
if (s_ObjectSpawnFinishedMessage.state == 0U)
{
PrepareToSpawnSceneObjects();
s_IsSpawnFinished = false;
}
else
{
foreach (var networkIdentity in Objects.Values)
{
if (!networkIdentity.IsClient)
{
networkIdentity.OnStartClient();
CheckForOwner(networkIdentity);
}
}
s_IsSpawnFinished = true;
}
}
private static void OnObjectDestroy(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectDestroyMessage>(s_ObjectDestroyMessage);
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::OnObjDestroy netId:" + s_ObjectDestroyMessage.netId);
}
if (s_NetworkScene.GetNetworkIdentity(s_ObjectDestroyMessage.netId, out var networkIdentity))
{
networkIdentity.OnNetworkDestroy();
if (!QSBNetworkScene.InvokeUnSpawnHandler(networkIdentity.AssetId, networkIdentity.gameObject))
{
if (networkIdentity.SceneId.IsEmpty())
{
UnityEngine.Object.Destroy(networkIdentity.gameObject);
}
else
{
networkIdentity.gameObject.SetActive(false);
SpawnableObjects[networkIdentity.SceneId] = networkIdentity;
}
}
s_NetworkScene.RemoveLocalObject(s_ObjectDestroyMessage.netId);
networkIdentity.MarkForReset();
}
else if (LogFilter.logDebug)
{
Debug.LogWarning("Did not find target for destroy message for " + s_ObjectDestroyMessage.netId);
}
}
private static void OnLocalClientObjectDestroy(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectDestroyMessage>(s_ObjectDestroyMessage);
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::OnLocalObjectObjDestroy netId:" + s_ObjectDestroyMessage.netId);
}
s_NetworkScene.RemoveLocalObject(s_ObjectDestroyMessage.netId);
}
private static void OnLocalClientObjectHide(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectDestroyMessage>(s_ObjectDestroyMessage);
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::OnLocalObjectObjHide netId:" + s_ObjectDestroyMessage.netId);
}
if (s_NetworkScene.GetNetworkIdentity(s_ObjectDestroyMessage.netId, out var networkIdentity))
{
networkIdentity.OnSetLocalVisibility(false);
}
}
private static void OnLocalClientObjectSpawn(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectSpawnMessage>(s_ObjectSpawnMessage);
if (s_NetworkScene.GetNetworkIdentity(s_ObjectSpawnMessage.netId, out var networkIdentity))
{
networkIdentity.OnSetLocalVisibility(true);
}
}
private static void OnLocalClientObjectSpawnScene(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBObjectSpawnSceneMessage>(s_ObjectSpawnSceneMessage);
if (s_NetworkScene.GetNetworkIdentity(s_ObjectSpawnSceneMessage.netId, out var networkIdentity))
{
networkIdentity.OnSetLocalVisibility(true);
}
}
private static void OnUpdateVarsMessage(QSBNetworkMessage netMsg)
{
var networkInstanceId = netMsg.reader.ReadNetworkId();
Debug.Log(string.Concat(new object[]
{
"ClientScene::OnUpdateVarsMessage ",
networkInstanceId,
" channel:",
netMsg.channelId
}));
if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity))
{
networkIdentity.OnUpdateVars(netMsg.reader, false);
}
else if (LogFilter.logWarn)
{
Debug.LogWarning("Did not find target for sync message for " + networkInstanceId);
}
}
private static void OnRPCMessage(QSBNetworkMessage netMsg)
{
var num = (int)netMsg.reader.ReadPackedUInt32();
var networkInstanceId = netMsg.reader.ReadNetworkId();
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"ClientScene::OnRPCMessage hash:",
num,
" netId:",
networkInstanceId
}));
}
if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity))
{
networkIdentity.HandleRPC(num, netMsg.reader);
}
else if (LogFilter.logWarn)
{
string cmdHashHandlerName = QSBNetworkBehaviour.GetCmdHashHandlerName(num);
Debug.LogWarningFormat("Could not find target object with netId:{0} for RPC call {1}", new object[]
{
networkInstanceId,
cmdHashHandlerName
});
}
}
private static void OnSyncEventMessage(QSBNetworkMessage netMsg)
{
var cmdHash = (int)netMsg.reader.ReadPackedUInt32();
var networkInstanceId = netMsg.reader.ReadNetworkId();
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::OnSyncEventMessage " + networkInstanceId);
}
if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity))
{
networkIdentity.HandleSyncEvent(cmdHash, netMsg.reader);
}
else if (LogFilter.logWarn)
{
Debug.LogWarning("Did not find target for SyncEvent message for " + networkInstanceId);
}
}
private static void OnSyncListMessage(QSBNetworkMessage netMsg)
{
var networkInstanceId = netMsg.reader.ReadNetworkId();
var cmdHash = (int)netMsg.reader.ReadPackedUInt32();
if (LogFilter.logDebug)
{
Debug.Log("ClientScene::OnSyncListMessage " + networkInstanceId);
}
if (s_NetworkScene.GetNetworkIdentity(networkInstanceId, out var networkIdentity))
{
networkIdentity.HandleSyncList(cmdHash, netMsg.reader);
}
else if (LogFilter.logWarn)
{
Debug.LogWarning("Did not find target for SyncList message for " + networkInstanceId);
}
}
private static void OnClientAuthority(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBClientAuthorityMessage>(s_ClientAuthorityMessage);
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"ClientScene::OnClientAuthority for connectionId=",
netMsg.conn.connectionId,
" netId: ",
s_ClientAuthorityMessage.netId
}));
}
if (s_NetworkScene.GetNetworkIdentity(s_ClientAuthorityMessage.netId, out var networkIdentity))
{
networkIdentity.HandleClientAuthority(s_ClientAuthorityMessage.authority);
}
}
private static void OnOwnerMessage(QSBNetworkMessage netMsg)
{
netMsg.ReadMessage<QSBOwnerMessage>(s_OwnerMessage);
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"ClientScene::OnOwnerMessage - connectionId=",
netMsg.conn.connectionId,
" netId: ",
s_OwnerMessage.netId
}));
}
if (netMsg.conn.GetPlayerController(s_OwnerMessage.playerControllerId, out var playerController))
{
playerController.unetView.SetNotLocalPlayer();
}
if (s_NetworkScene.GetNetworkIdentity(s_OwnerMessage.netId, out var networkIdentity))
{
networkIdentity.SetConnectionToServer(netMsg.conn);
networkIdentity.SetLocalPlayer(s_OwnerMessage.playerControllerId);
InternalAddPlayer(networkIdentity, s_OwnerMessage.playerControllerId);
}
else
{
var item = new PendingOwner
{
netId = s_OwnerMessage.netId,
playerControllerId = s_OwnerMessage.playerControllerId
};
s_PendingOwnerIds.Add(item);
}
}
private static void CheckForOwner(QSBNetworkIdentity uv)
{
var i = 0;
while (i < s_PendingOwnerIds.Count)
{
var pendingOwner = s_PendingOwnerIds[i];
if (pendingOwner.netId == uv.NetId)
{
uv.SetConnectionToServer(readyConnection);
uv.SetLocalPlayer(pendingOwner.playerControllerId);
Debug.Log("ClientScene::OnOwnerMessage - player=" + uv.gameObject.name);
if (readyConnection.connectionId < 0)
{
if (LogFilter.logError)
{
Debug.LogError("Owner message received on a local client.");
}
break;
}
InternalAddPlayer(uv, pendingOwner.playerControllerId);
s_PendingOwnerIds.RemoveAt(i);
break;
}
else
{
i++;
}
}
}
private static bool s_IsSpawnFinished;
private static QSBNetworkScene s_NetworkScene = new QSBNetworkScene();
private static QSBObjectSpawnSceneMessage s_ObjectSpawnSceneMessage = new QSBObjectSpawnSceneMessage();
private static QSBObjectSpawnFinishedMessage s_ObjectSpawnFinishedMessage = new QSBObjectSpawnFinishedMessage();
private static QSBObjectDestroyMessage s_ObjectDestroyMessage = new QSBObjectDestroyMessage();
private static QSBObjectSpawnMessage s_ObjectSpawnMessage = new QSBObjectSpawnMessage();
private static QSBOwnerMessage s_OwnerMessage = new QSBOwnerMessage();
private static QSBClientAuthorityMessage s_ClientAuthorityMessage = new QSBClientAuthorityMessage();
public const int ReconnectIdInvalid = -1;
public const int ReconnectIdHost = 0;
private static PeerInfoMessage[] s_Peers;
private static List<PendingOwner> s_PendingOwnerIds = new List<PendingOwner>();
private struct PendingOwner
{
public NetworkInstanceId netId;
public short playerControllerId;
}
}
}

162
QSB/QSBLocalClient.cs Normal file
View File

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
namespace QSB
{
class QSBLocalClient : QSBNetworkClient
{
public override void Disconnect()
{
QSBClientScene.HandleClientDisconnect(m_Connection);
if (m_Connected)
{
PostInternalMessage(33);
m_Connected = false;
}
m_AsyncConnect = QSBNetworkClient.ConnectState.Disconnected;
m_LocalServer.RemoveLocalClient(m_Connection);
}
internal void InternalConnectLocalServer(bool generateConnectMsg)
{
if (m_FreeMessages == null)
{
m_FreeMessages = new Stack<InternalMsg>();
for (var i = 0; i < 64; i++)
{
var t = default(InternalMsg);
m_FreeMessages.Push(t);
}
}
m_LocalServer = QSBNetworkServer.instance;
m_Connection = new ULocalConnectionToServer(m_LocalServer);
base.SetHandlers(m_Connection);
m_Connection.connectionId = m_LocalServer.AddLocalClient(this);
m_AsyncConnect = QSBNetworkClient.ConnectState.Connected;
QSBNetworkClient.SetActive(true);
base.RegisterSystemHandlers(true);
if (generateConnectMsg)
{
PostInternalMessage(32);
}
m_Connected = true;
}
internal override void Update() => ProcessInternalMessages();
internal void AddLocalPlayer(QSBPlayerController localPlayer)
{
Debug.Log(string.Concat(new object[]
{
"Local client AddLocalPlayer ",
localPlayer.gameObject.name,
" conn=",
m_Connection.connectionId
}));
m_Connection.isReady = true;
m_Connection.SetPlayerController(localPlayer);
var unetView = localPlayer.unetView;
if (unetView != null)
{
QSBClientScene.SetLocalObject(unetView.NetId, localPlayer.gameObject);
unetView.SetConnectionToServer(m_Connection);
}
QSBClientScene.InternalAddPlayer(unetView, localPlayer.playerControllerId);
}
private void PostInternalMessage(byte[] buffer, int channelId)
{
InternalMsg item;
if (m_FreeMessages.Count == 0)
{
item = default;
}
else
{
item = m_FreeMessages.Pop();
}
item.buffer = buffer;
item.channelId = channelId;
m_InternalMsgs.Add(item);
}
private void PostInternalMessage(short msgType)
{
var networkWriter = new NetworkWriter();
networkWriter.StartMessage(msgType);
networkWriter.FinishMessage();
PostInternalMessage(networkWriter.AsArray(), 0);
}
private void ProcessInternalMessages()
{
if (m_InternalMsgs.Count != 0)
{
var internalMsgs = m_InternalMsgs;
m_InternalMsgs = m_InternalMsgs2;
for (var i = 0; i < internalMsgs.Count; i++)
{
var t = internalMsgs[i];
if (s_InternalMessage.reader == null)
{
s_InternalMessage.reader = new NetworkReader(t.buffer);
}
else
{
s_InternalMessage.reader.Replace(t.buffer);
}
s_InternalMessage.reader.ReadInt16();
s_InternalMessage.channelId = t.channelId;
s_InternalMessage.conn = base.connection;
s_InternalMessage.msgType = s_InternalMessage.reader.ReadInt16();
m_Connection.InvokeHandler(s_InternalMessage);
m_FreeMessages.Push(t);
base.connection.lastMessageTime = Time.time;
}
m_InternalMsgs = internalMsgs;
m_InternalMsgs.Clear();
for (var j = 0; j < m_InternalMsgs2.Count; j++)
{
m_InternalMsgs.Add(m_InternalMsgs2[j]);
}
m_InternalMsgs2.Clear();
}
}
internal void InvokeHandlerOnClient(short msgType, MessageBase msg, int channelId)
{
var networkWriter = new NetworkWriter();
networkWriter.StartMessage(msgType);
msg.Serialize(networkWriter);
networkWriter.FinishMessage();
InvokeBytesOnClient(networkWriter.AsArray(), channelId);
}
internal void InvokeBytesOnClient(byte[] buffer, int channelId) => PostInternalMessage(buffer, channelId);
private const int k_InitialFreeMessagePoolSize = 64;
private List<InternalMsg> m_InternalMsgs = new List<InternalMsg>();
private readonly List<InternalMsg> m_InternalMsgs2 = new List<InternalMsg>();
private Stack<InternalMsg> m_FreeMessages;
private QSBNetworkServer m_LocalServer;
private bool m_Connected;
private readonly QSBNetworkMessage s_InternalMessage = new QSBNetworkMessage();
private struct InternalMsg
{
internal byte[] buffer;
internal int channelId;
}
}
}

View File

@ -15,8 +15,8 @@ namespace QSB
public bool IsLocalPlayer => MyView.IsLocalPlayer;
public bool HasAuthority => MyView.HasAuthority;
public NetworkInstanceId NetId => MyView.NetId;
public NetworkConnection ConnectionToServer => MyView.ConnectionToServer;
public NetworkConnection ConnectionToClient => MyView.ConnectionToClient;
public QSBNetworkConnection ConnectionToServer => MyView.ConnectionToServer;
public QSBNetworkConnection ConnectionToClient => MyView.ConnectionToClient;
public short PlayerControllerId => MyView.PlayerControllerId;
protected uint SyncVarDirtyBits { get; private set; }
@ -52,14 +52,14 @@ namespace QSB
{
Debug.LogWarning("Trying to send command for object without authority.");
}
else if (ClientScene.readyConnection == null)
else if (QSBClientScene.readyConnection == null)
{
Debug.LogError("Send command attempted with no client running [client=" + ConnectionToServer + "].");
}
else
{
writer.FinishMessage();
ClientScene.readyConnection.SendWriter(writer, channelId);
QSBClientScene.readyConnection.SendWriter(writer, channelId);
}
}
@ -558,7 +558,7 @@ namespace QSB
public virtual void OnStartLocalPlayer() { }
public virtual void OnStartAuthority() { }
public virtual void OnStopAuthority() { }
public virtual bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initialize) => false;
public virtual bool OnRebuildObservers(HashSet<QSBNetworkConnection> observers, bool initialize) => false;
public virtual void OnSetLocalVisibility(bool vis) { }
public virtual bool OnCheckObserver(NetworkConnection conn) => true;
public virtual int GetNetworkChannel() => 0;

1213
QSB/QSBNetworkClient.cs Normal file

File diff suppressed because it is too large Load Diff

561
QSB/QSBNetworkConnection.cs Normal file
View File

@ -0,0 +1,561 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
namespace QSB
{
public class QSBNetworkConnection : IDisposable
{
public QSBNetworkConnection()
{
m_Writer = new NetworkWriter();
}
internal HashSet<QSBNetworkIdentity> VisList { get; } = new HashSet<QSBNetworkIdentity>();
public List<QSBPlayerController> PlayerControllers { get; } = new List<QSBPlayerController>();
public HashSet<NetworkInstanceId> ClientOwnedObjects { get; private set; }
public bool isConnected => hostId != -1;
public NetworkError LastError { get; internal set; }
internal Dictionary<short, PacketStat> PacketStats { get; } = new Dictionary<short, PacketStat>();
public virtual void Initialize(string networkAddress, int networkHostId, int networkConnectionId, HostTopology hostTopology)
{
m_Writer = new NetworkWriter();
address = networkAddress;
hostId = networkHostId;
connectionId = networkConnectionId;
var channelCount = hostTopology.DefaultConfig.ChannelCount;
var packetSize = (int)hostTopology.DefaultConfig.PacketSize;
if (hostTopology.DefaultConfig.UsePlatformSpecificProtocols && Application.platform != RuntimePlatform.PS4 && Application.platform != RuntimePlatform.PSP2)
{
throw new ArgumentOutOfRangeException("Platform specific protocols are not supported on this platform");
}
m_Channels = new ChannelBuffer[channelCount];
for (var i = 0; i < channelCount; i++)
{
var channelQOS = hostTopology.DefaultConfig.Channels[i];
var bufferSize = packetSize;
if (channelQOS.QOS == QosType.ReliableFragmented || channelQOS.QOS == QosType.UnreliableFragmented)
{
bufferSize = (int)(hostTopology.DefaultConfig.FragmentSize * 128);
}
m_Channels[i] = new ChannelBuffer(this, bufferSize, (byte)i, IsReliableQoS(channelQOS.QOS), IsSequencedQoS(channelQOS.QOS));
}
}
~QSBNetworkConnection()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!m_Disposed && m_Channels != null)
{
for (var i = 0; i < m_Channels.Length; i++)
{
m_Channels[i].Dispose();
}
}
m_Channels = null;
if (ClientOwnedObjects != null)
{
foreach (var netId in ClientOwnedObjects)
{
var gameObject = NetworkServer.FindLocalObject(netId);
if (gameObject != null)
{
gameObject.GetComponent<QSBNetworkIdentity>().ClearClientOwner();
}
}
}
ClientOwnedObjects = null;
m_Disposed = true;
}
private static bool IsSequencedQoS(QosType qos) => qos == QosType.ReliableSequenced || qos == QosType.UnreliableSequenced;
private static bool IsReliableQoS(QosType qos) => qos == QosType.Reliable || qos == QosType.ReliableFragmented || qos == QosType.ReliableSequenced || qos == QosType.ReliableStateUpdate;
public bool SetChannelOption(int channelId, ChannelOption option, int value) => m_Channels != null && channelId >= 0 && channelId < m_Channels.Length && m_Channels[channelId].SetOption(option, value);
public void Disconnect()
{
address = "";
isReady = false;
QSBClientScene.HandleClientDisconnect(this);
if (hostId != -1)
{
byte b;
NetworkTransport.Disconnect(hostId, connectionId, out b);
RemoveObservers();
}
}
internal void SetHandlers(QSBNetworkMessageHandlers handlers)
{
m_MessageHandlers = handlers;
m_MessageHandlersDict = handlers.GetHandlers();
}
public bool CheckHandler(short msgType) => m_MessageHandlersDict.ContainsKey(msgType);
public bool InvokeHandlerNoData(short msgType) => InvokeHandler(msgType, null, 0);
public bool InvokeHandler(short msgType, NetworkReader reader, int channelId)
{
bool result;
if (m_MessageHandlersDict.ContainsKey(msgType))
{
m_MessageInfo.msgType = msgType;
m_MessageInfo.conn = this;
m_MessageInfo.reader = reader;
m_MessageInfo.channelId = channelId;
var networkMessageDelegate = m_MessageHandlersDict[msgType];
if (networkMessageDelegate == null)
{
if (LogFilter.logError)
{
Debug.LogError("NetworkConnection InvokeHandler no handler for " + msgType);
}
result = false;
}
else
{
networkMessageDelegate(m_MessageInfo);
result = true;
}
}
else
{
result = false;
}
return result;
}
public bool InvokeHandler(QSBNetworkMessage netMsg)
{
bool result;
if (m_MessageHandlersDict.ContainsKey(netMsg.msgType))
{
var networkMessageDelegate = m_MessageHandlersDict[netMsg.msgType];
networkMessageDelegate(netMsg);
result = true;
}
else
{
result = false;
}
return result;
}
internal void HandleFragment(NetworkReader reader, int channelId)
{
if (channelId >= 0 && channelId < m_Channels.Length)
{
var channelBuffer = m_Channels[channelId];
if (channelBuffer.HandleFragment(reader))
{
var networkReader = new NetworkReader(channelBuffer.fragmentBuffer.AsArraySegment().Array);
networkReader.ReadInt16();
var msgType = networkReader.ReadInt16();
InvokeHandler(msgType, networkReader, channelId);
}
}
}
public void RegisterHandler(short msgType, QSBNetworkMessageDelegate handler) => m_MessageHandlers.RegisterHandler(msgType, handler);
public void UnregisterHandler(short msgType) => m_MessageHandlers.UnregisterHandler(msgType);
internal void SetPlayerController(QSBPlayerController player)
{
while ((int)player.playerControllerId >= PlayerControllers.Count)
{
PlayerControllers.Add(new QSBPlayerController());
}
PlayerControllers[(int)player.playerControllerId] = player;
}
internal void RemovePlayerController(short playerControllerId)
{
for (var i = PlayerControllers.Count; i >= 0; i--)
{
if ((int)playerControllerId == i && playerControllerId == PlayerControllers[i].playerControllerId)
{
PlayerControllers[i] = new QSBPlayerController();
return;
}
}
if (LogFilter.logError)
{
Debug.LogError("RemovePlayer player at playerControllerId " + playerControllerId + " not found");
return;
}
}
internal bool GetPlayerController(short playerControllerId, out QSBPlayerController playerController)
{
playerController = null;
bool result;
if (PlayerControllers.Count > 0)
{
for (var i = 0; i < PlayerControllers.Count; i++)
{
if (PlayerControllers[i].IsValid && PlayerControllers[i].playerControllerId == playerControllerId)
{
playerController = PlayerControllers[i];
return true;
}
}
result = false;
}
else
{
result = false;
}
return result;
}
public void FlushChannels()
{
if (m_Channels != null)
{
for (var i = 0; i < m_Channels.Length; i++)
{
m_Channels[i].CheckInternalBuffer();
}
}
}
public void SetMaxDelay(float seconds)
{
if (m_Channels != null)
{
for (var i = 0; i < m_Channels.Length; i++)
{
m_Channels[i].maxDelay = seconds;
}
}
}
public virtual bool Send(short msgType, MessageBase msg) => SendByChannel(msgType, msg, 0);
public virtual bool SendUnreliable(short msgType, MessageBase msg) => SendByChannel(msgType, msg, 1);
public virtual bool SendByChannel(short msgType, MessageBase msg, int channelId)
{
m_Writer.StartMessage(msgType);
msg.Serialize(m_Writer);
m_Writer.FinishMessage();
return SendWriter(m_Writer, channelId);
}
public virtual bool SendBytes(byte[] bytes, int numBytes, int channelId)
{
if (logNetworkMessages)
{
LogSend(bytes);
}
return CheckChannel(channelId) && m_Channels[channelId].SendBytes(bytes, numBytes);
}
public virtual bool SendWriter(NetworkWriter writer, int channelId)
{
if (logNetworkMessages)
{
LogSend(writer.ToArray());
}
return CheckChannel(channelId) && m_Channels[channelId].SendWriter(writer);
}
private void LogSend(byte[] bytes)
{
var networkReader = new NetworkReader(bytes);
var num = networkReader.ReadUInt16();
var num2 = networkReader.ReadUInt16();
var stringBuilder = new StringBuilder();
for (var i = 4; i < (int)(4 + num); i++)
{
stringBuilder.AppendFormat("{0:X2}", bytes[i]);
if (i > 150)
{
break;
}
}
Debug.Log(string.Concat(new object[]
{
"ConnectionSend con:",
connectionId,
" bytes:",
num,
" msgId:",
num2,
" ",
stringBuilder
}));
}
private bool CheckChannel(int channelId)
{
bool result;
if (m_Channels == null)
{
if (LogFilter.logWarn)
{
Debug.LogWarning("Channels not initialized sending on id '" + channelId);
}
result = false;
}
else if (channelId < 0 || channelId >= m_Channels.Length)
{
if (LogFilter.logError)
{
Debug.LogError(string.Concat(new object[]
{
"Invalid channel when sending buffered data, '",
channelId,
"'. Current channel count is ",
m_Channels.Length
}));
}
result = false;
}
else
{
result = true;
}
return result;
}
public void ResetStats()
{
}
protected void HandleBytes(byte[] buffer, int receivedSize, int channelId)
{
var reader = new NetworkReader(buffer);
HandleReader(reader, receivedSize, channelId);
}
protected void HandleReader(NetworkReader reader, int receivedSize, int channelId)
{
while ((ulong)reader.Position < (ulong)((long)receivedSize))
{
var num = reader.ReadUInt16();
var num2 = reader.ReadInt16();
var array = reader.ReadBytes((int)num);
var reader2 = new NetworkReader(array);
if (logNetworkMessages)
{
var stringBuilder = new StringBuilder();
for (var i = 0; i < (int)num; i++)
{
stringBuilder.AppendFormat("{0:X2}", array[i]);
if (i > 150)
{
break;
}
}
Debug.Log(string.Concat(new object[]
{
"ConnectionRecv con:",
connectionId,
" bytes:",
num,
" msgId:",
num2,
" ",
stringBuilder
}));
}
QSBNetworkMessageDelegate networkMessageDelegate = null;
if (m_MessageHandlersDict.ContainsKey(num2))
{
networkMessageDelegate = m_MessageHandlersDict[num2];
}
if (networkMessageDelegate == null)
{
if (LogFilter.logError)
{
Debug.LogError(string.Concat(new object[]
{
"Unknown message ID ",
num2,
" connId:",
connectionId
}));
}
break;
}
m_NetMsg.msgType = num2;
m_NetMsg.reader = reader2;
m_NetMsg.conn = this;
m_NetMsg.channelId = channelId;
networkMessageDelegate(m_NetMsg);
lastMessageTime = Time.time;
}
}
public virtual void GetStatsOut(out int numMsgs, out int numBufferedMsgs, out int numBytes, out int lastBufferedPerSecond)
{
numMsgs = 0;
numBufferedMsgs = 0;
numBytes = 0;
lastBufferedPerSecond = 0;
for (var i = 0; i < m_Channels.Length; i++)
{
var channelBuffer = m_Channels[i];
numMsgs += channelBuffer.numMsgsOut;
numBufferedMsgs += channelBuffer.numBufferedMsgsOut;
numBytes += channelBuffer.numBytesOut;
lastBufferedPerSecond += channelBuffer.lastBufferedPerSecond;
}
}
public virtual void GetStatsIn(out int numMsgs, out int numBytes)
{
numMsgs = 0;
numBytes = 0;
for (var i = 0; i < m_Channels.Length; i++)
{
var channelBuffer = m_Channels[i];
numMsgs += channelBuffer.numMsgsIn;
numBytes += channelBuffer.numBytesIn;
}
}
public override string ToString()
{
return string.Format("hostId: {0} connectionId: {1} isReady: {2} channel count: {3}", new object[]
{
hostId,
connectionId,
isReady,
(m_Channels == null) ? 0 : m_Channels.Length
});
}
internal void AddToVisList(QSBNetworkIdentity uv)
{
VisList.Add(uv);
QSBNetworkServer.ShowForConnection(uv, this);
}
internal void RemoveFromVisList(QSBNetworkIdentity uv, bool isDestroyed)
{
VisList.Remove(uv);
if (!isDestroyed)
{
QSBNetworkServer.HideForConnection(uv, this);
}
}
internal void RemoveObservers()
{
foreach (var networkIdentity in VisList)
{
networkIdentity.RemoveObserverInternal(this);
}
VisList.Clear();
}
public virtual void TransportReceive(byte[] bytes, int numBytes, int channelId) => HandleBytes(bytes, numBytes, channelId);
[Obsolete("TransportRecieve has been deprecated. Use TransportReceive instead (UnityUpgradable) -> TransportReceive(*)", false)]
public virtual void TransportRecieve(byte[] bytes, int numBytes, int channelId) => TransportReceive(bytes, numBytes, channelId);
public virtual bool TransportSend(byte[] bytes, int numBytes, int channelId, out byte error) => NetworkTransport.Send(hostId, connectionId, channelId, bytes, numBytes, out error);
internal void AddOwnedObject(QSBNetworkIdentity obj)
{
if (ClientOwnedObjects == null)
{
ClientOwnedObjects = new HashSet<NetworkInstanceId>();
}
ClientOwnedObjects.Add(obj.NetId);
}
internal void RemoveOwnedObject(QSBNetworkIdentity obj)
{
if (ClientOwnedObjects != null)
{
ClientOwnedObjects.Remove(obj.NetId);
}
}
internal static void OnFragment(QSBNetworkMessage netMsg) => netMsg.conn.HandleFragment(netMsg.reader, netMsg.channelId);
private ChannelBuffer[] m_Channels;
private readonly QSBNetworkMessage m_NetMsg = new QSBNetworkMessage();
private NetworkWriter m_Writer;
private Dictionary<short, QSBNetworkMessageDelegate> m_MessageHandlersDict;
private QSBNetworkMessageHandlers m_MessageHandlers;
private readonly QSBNetworkMessage m_MessageInfo = new QSBNetworkMessage();
private const int k_MaxMessageLogSize = 150;
public int hostId = -1;
public int connectionId = -1;
public bool isReady;
public string address;
public float lastMessageTime;
public bool logNetworkMessages = false;
private bool m_Disposed;
public class PacketStat
{
public PacketStat()
{
msgType = 0;
count = 0;
bytes = 0;
}
public PacketStat(PacketStat s)
{
msgType = s.msgType;
count = s.count;
bytes = s.bytes;
}
public override string ToString()
{
return string.Concat(new object[]
{
MsgType.MsgTypeToString(msgType),
": count=",
count,
" bytes=",
bytes
});
}
public short msgType;
public int count;
public int bytes;
}
}
}

View File

@ -15,12 +15,12 @@ namespace QSB
public bool HasAuthority { get; private set; }
public NetworkInstanceId NetId { get; private set; }
public NetworkSceneId SceneId => m_SceneId;
public NetworkConnection ClientAuthorityOwner { get; private set; }
public QSBNetworkConnection ClientAuthorityOwner { get; private set; }
public NetworkHash128 AssetId => m_AssetId;
public bool IsLocalPlayer { get; private set; }
public short PlayerControllerId { get; private set; } = -1;
public NetworkConnection ConnectionToServer { get; private set; }
public NetworkConnection ConnectionToClient { get; private set; }
public QSBNetworkConnection ConnectionToServer { get; private set; }
public QSBNetworkConnection ConnectionToClient { get; private set; }
public bool ServerOnly
{
@ -58,7 +58,7 @@ namespace QSB
}
}
internal void SetClientOwner(NetworkConnection conn)
internal void SetClientOwner(QSBNetworkConnection conn)
{
if (ClientAuthorityOwner != null)
{
@ -88,18 +88,18 @@ namespace QSB
public ReadOnlyCollection<NetworkConnection> Observers
public ReadOnlyCollection<QSBNetworkConnection> Observers
{
get
{
ReadOnlyCollection<NetworkConnection> result;
ReadOnlyCollection<QSBNetworkConnection> result;
if (m_Observers == null)
{
result = null;
}
else
{
result = new ReadOnlyCollection<NetworkConnection>(m_Observers);
result = new ReadOnlyCollection<QSBNetworkConnection>(m_Observers);
}
return result;
}
@ -154,7 +154,7 @@ namespace QSB
}
}
internal void RemoveObserverInternal(NetworkConnection conn)
internal void RemoveObserverInternal(QSBNetworkConnection conn)
{
if (m_Observers != null)
{
@ -184,7 +184,7 @@ namespace QSB
{
HasAuthority = true;
}
m_Observers = new List<NetworkConnection>();
m_Observers = new List<QSBNetworkConnection>();
m_ObserverConnections = new HashSet<int>();
CacheBehaviours();
if (NetId.IsEmpty())
@ -225,7 +225,7 @@ namespace QSB
}
if (NetworkClient.active && NetworkServer.localClientActive)
{
ClientScene.SetLocalObject(NetId, base.gameObject);
QSBClientScene.SetLocalObject(NetId, base.gameObject);
OnStartClient();
}
if (HasAuthority)
@ -676,9 +676,9 @@ namespace QSB
}
}
internal void SetConnectionToServer(NetworkConnection conn) => ConnectionToServer = conn;
internal void SetConnectionToServer(QSBNetworkConnection conn) => ConnectionToServer = conn;
internal void SetConnectionToClient(NetworkConnection conn, short newPlayerControllerId)
internal void SetConnectionToClient(QSBNetworkConnection conn, short newPlayerControllerId)
{
PlayerControllerId = newPlayerControllerId;
ConnectionToClient = conn;
@ -711,7 +711,7 @@ namespace QSB
}
}
internal void AddObserver(NetworkConnection conn)
internal void AddObserver(QSBNetworkConnection conn)
{
if (m_Observers == null)
{
@ -742,7 +742,7 @@ namespace QSB
}
}
internal void RemoveObserver(NetworkConnection conn)
internal void RemoveObserver(QSBNetworkConnection conn)
{
if (m_Observers != null)
{
@ -758,8 +758,8 @@ namespace QSB
{
var flag = false;
var flag2 = false;
var hashSet = new HashSet<NetworkConnection>();
var hashSet2 = new HashSet<NetworkConnection>(m_Observers);
var hashSet = new HashSet<QSBNetworkConnection>();
var hashSet2 = new HashSet<QSBNetworkConnection>(m_Observers);
for (var i = 0; i < m_NetworkBehaviours.Length; i++)
{
var networkBehaviour = m_NetworkBehaviours[i];
@ -769,9 +769,9 @@ namespace QSB
{
if (initialize)
{
for (var j = 0; j < NetworkServer.connections.Count; j++)
for (var j = 0; j < QSBNetworkServer.connections.Count; j++)
{
var networkConnection = NetworkServer.connections[j];
var networkConnection = QSBNetworkServer.connections[j];
if (networkConnection != null)
{
if (networkConnection.isReady)
@ -780,9 +780,9 @@ namespace QSB
}
}
}
for (var k = 0; k < NetworkServer.localConnections.Count; k++)
for (var k = 0; k < QSBNetworkServer.localConnections.Count; k++)
{
var networkConnection2 = NetworkServer.localConnections[k];
var networkConnection2 = QSBNetworkServer.localConnections[k];
if (networkConnection2 != null)
{
if (networkConnection2.isReady)
@ -840,9 +840,9 @@ namespace QSB
}
if (initialize)
{
for (var l = 0; l < NetworkServer.localConnections.Count; l++)
for (var l = 0; l < QSBNetworkServer.localConnections.Count; l++)
{
if (!hashSet.Contains(NetworkServer.localConnections[l]))
if (!hashSet.Contains(QSBNetworkServer.localConnections[l]))
{
OnSetLocalVisibility(false);
}
@ -850,7 +850,7 @@ namespace QSB
}
if (flag)
{
m_Observers = new List<NetworkConnection>(hashSet);
m_Observers = new List<QSBNetworkConnection>(hashSet);
m_ObserverConnections.Clear();
for (var m = 0; m < m_Observers.Count; m++)
{
@ -861,7 +861,7 @@ namespace QSB
}
}
public bool RemoveClientAuthority(NetworkConnection conn)
public bool RemoveClientAuthority(QSBNetworkConnection conn)
{
bool result;
if (!IsServer)
@ -889,20 +889,18 @@ namespace QSB
ClientAuthorityOwner.GetType().GetMethod("RemoveOwnedObject", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Invoke(ClientAuthorityOwner, new object[] { this });
ClientAuthorityOwner = null;
ForceAuthority(true);
/*
conn.Send(15, new ClientAuthorityMessage
conn.Send(15, new QSBClientAuthorityMessage
{
netId = NetId,
authority = false
});
*/
clientAuthorityCallback?.Invoke(conn, this, false);
result = true;
}
return result;
}
public bool AssignClientAuthority(NetworkConnection conn)
public bool AssignClientAuthority(QSBNetworkConnection conn)
{
bool result;
if (!IsServer)
@ -931,13 +929,11 @@ namespace QSB
ClientAuthorityOwner.GetType().GetMethod("AddOwnedObject", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Invoke(ClientAuthorityOwner, new object[] { this });
ForceAuthority(false);
/*
conn.Send(15, new ClientAuthorityMessage
conn.Send(15, new QSBClientAuthorityMessage
{
netId = NetId,
authority = true
});
*/
clientAuthorityCallback?.Invoke(conn, this, true);
result = true;
}
@ -988,7 +984,7 @@ namespace QSB
private HashSet<int> m_ObserverConnections;
private List<NetworkConnection> m_Observers;
private List<QSBNetworkConnection> m_Observers;
private bool m_Reset = false;
private static uint s_NextNetworkId = 1U;
@ -997,6 +993,6 @@ namespace QSB
public static ClientAuthorityCallback clientAuthorityCallback;
public delegate void ClientAuthorityCallback(NetworkConnection conn, QSBNetworkIdentity uv, bool authorityState);
public delegate void ClientAuthorityCallback(QSBNetworkConnection conn, QSBNetworkIdentity uv, bool authorityState);
}
}

View File

@ -115,22 +115,22 @@ namespace QSB
WorldRegistry.OldDialogueTrees = Resources.FindObjectsOfTypeAll<CharacterDialogueTree>().ToList();
}
NetworkServer.UnregisterHandler(40);
NetworkServer.UnregisterHandler(41);
NetworkServer.UnregisterHandler(42);
NetworkServer.RegisterHandler(40, new NetworkMessageDelegate(QSBNetworkAnimator.OnAnimationServerMessage));
NetworkServer.RegisterHandler(41, new NetworkMessageDelegate(QSBNetworkAnimator.OnAnimationParametersServerMessage));
NetworkServer.RegisterHandler(42, new NetworkMessageDelegate(QSBNetworkAnimator.OnAnimationTriggerServerMessage));
QSBNetworkServer.UnregisterHandler(40);
QSBNetworkServer.UnregisterHandler(41);
QSBNetworkServer.UnregisterHandler(42);
QSBNetworkServer.RegisterHandler(40, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationServerMessage));
QSBNetworkServer.RegisterHandler(41, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationParametersServerMessage));
QSBNetworkServer.RegisterHandler(42, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationTriggerServerMessage));
}
public override void OnServerAddPlayer(NetworkConnection connection, short playerControllerId) // Called on the server when a client joins
public override void OnServerAddPlayer(QSBNetworkConnection connection, short playerControllerId) // Called on the server when a client joins
{
DebugLog.DebugWrite("OnServerAddPlayer", MessageType.Info);
base.OnServerAddPlayer(connection, playerControllerId);
NetworkServer.SpawnWithClientAuthority(Instantiate(_shipPrefab), connection);
NetworkServer.SpawnWithClientAuthority(Instantiate(_cameraPrefab), connection);
NetworkServer.SpawnWithClientAuthority(Instantiate(_probePrefab), connection);
QSBNetworkServer.SpawnWithClientAuthority(Instantiate(_shipPrefab), connection);
QSBNetworkServer.SpawnWithClientAuthority(Instantiate(_cameraPrefab), connection);
QSBNetworkServer.SpawnWithClientAuthority(Instantiate(_probePrefab), connection);
}
public override void OnClientConnect(NetworkConnection connection) // Called on the client when connecting to a server
@ -153,11 +153,11 @@ namespace QSB
QSBPatchManager.DoPatchType(QSBPatchTypes.OnNonServerClientConnect);
singleton.client.UnregisterHandler(40);
singleton.client.UnregisterHandler(41);
singleton.client.RegisterHandlerSafe(40, new NetworkMessageDelegate(QSBNetworkAnimator.OnAnimationClientMessage));
singleton.client.RegisterHandlerSafe(41, new NetworkMessageDelegate(QSBNetworkAnimator.OnAnimationParametersClientMessage));
singleton.client.RegisterHandlerSafe(40, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationClientMessage));
singleton.client.RegisterHandlerSafe(41, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationParametersClientMessage));
}
singleton.client.UnregisterHandler(42);
singleton.client.RegisterHandlerSafe(42, new NetworkMessageDelegate(QSBNetworkAnimator.OnAnimationTriggerClientMessage));
singleton.client.RegisterHandlerSafe(42, new QSBNetworkMessageDelegate(QSBNetworkAnimator.OnAnimationTriggerClientMessage));
QSBPatchManager.DoPatchType(QSBPatchTypes.OnClientConnect);
@ -201,11 +201,11 @@ namespace QSB
_lobby.CanEditName = true;
}
public override void OnServerDisconnect(NetworkConnection connection) // Called on the server when any client disconnects
public override void OnServerDisconnect(QSBNetworkConnection connection) // Called on the server when any client disconnects
{
DebugLog.DebugWrite("OnServerDisconnect", MessageType.Info);
var player = connection.GetPlayer();
var netIds = connection.clientOwnedObjects.Select(x => x.Value).ToArray();
var netIds = connection.ClientOwnedObjects.Select(x => x.Value).ToArray();
GlobalMessenger<uint, uint[]>.FireEvent(EventNames.QSBPlayerLeave, player.PlayerId, netIds);
foreach (var item in WorldRegistry.OrbSyncList)
@ -230,7 +230,7 @@ namespace QSB
QSBEventManager.Reset();
DebugLog.ToConsole("[S] Server stopped!", MessageType.Info);
QSBPlayerManager.PlayerList.ForEach(player => player.HudMarker?.Remove());
NetworkServer.connections.ToList().ForEach(CleanupConnection);
QSBNetworkServer.connections.ToList().ForEach(CleanupConnection);
WorldRegistry.RemoveObjects<QSBOrbSlot>();
WorldRegistry.RemoveObjects<QSBElevator>();
@ -240,13 +240,13 @@ namespace QSB
base.OnStopServer();
}
private void CleanupConnection(NetworkConnection connection)
private void CleanupConnection(QSBNetworkConnection connection)
{
var player = connection.GetPlayer();
DebugLog.ToConsole($"{player.Name} disconnected.", MessageType.Info);
QSBPlayerManager.RemovePlayer(player.PlayerId);
var netIds = connection.clientOwnedObjects?.Select(x => x.Value).ToList();
var netIds = connection.ClientOwnedObjects?.Select(x => x.Value).ToList();
netIds.ForEach(CleanupNetworkBehaviour);
}

43
QSB/QSBNetworkMessage.cs Normal file
View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Networking;
namespace QSB
{
public class QSBNetworkMessage
{
public static string Dump(byte[] payload, int sz)
{
var text = "[";
for (var i = 0; i < sz; i++)
{
text = text + payload[i] + " ";
}
return text + "]";
}
public TMsg ReadMessage<TMsg>() where TMsg : MessageBase, new()
{
var result = Activator.CreateInstance<TMsg>();
result.Deserialize(reader);
return result;
}
public void ReadMessage<TMsg>(TMsg msg) where TMsg : MessageBase
{
msg.Deserialize(reader);
}
public const int MaxMessageSize = 65535;
public short msgType;
public QSBNetworkConnection conn;
public NetworkReader reader;
public int channelId;
}
}

View File

@ -0,0 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace QSB
{
public delegate void QSBNetworkMessageDelegate(QSBNetworkMessage netMsg);
}

View File

@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
namespace QSB
{
class QSBNetworkMessageHandlers
{
internal void RegisterHandlerSafe(short msgType, QSBNetworkMessageDelegate handler)
{
if (handler == null)
{
Debug.LogError("RegisterHandlerSafe id:" + msgType + " handler is null");
}
else
{
Debug.Log(string.Concat(new object[]
{
"RegisterHandlerSafe id:",
msgType,
" handler:",
handler.GetMethodName()
}));
if (!this.m_MsgHandlers.ContainsKey(msgType))
{
this.m_MsgHandlers.Add(msgType, handler);
}
}
}
public void RegisterHandler(short msgType, QSBNetworkMessageDelegate handler)
{
if (handler == null)
{
Debug.LogError("RegisterHandler id:" + msgType + " handler is null");
}
else if (msgType <= 31)
{
Debug.LogError("RegisterHandler: Cannot replace system message handler " + msgType);
}
else
{
if (this.m_MsgHandlers.ContainsKey(msgType))
{
Debug.Log("RegisterHandler replacing " + msgType);
this.m_MsgHandlers.Remove(msgType);
}
Debug.Log(string.Concat(new object[]
{
"RegisterHandler id:",
msgType,
" handler:",
handler.GetMethodName()
}));
this.m_MsgHandlers.Add(msgType, handler);
}
}
public void UnregisterHandler(short msgType)
{
this.m_MsgHandlers.Remove(msgType);
}
internal QSBNetworkMessageDelegate GetHandler(short msgType)
{
QSBNetworkMessageDelegate result;
if (this.m_MsgHandlers.ContainsKey(msgType))
{
result = this.m_MsgHandlers[msgType];
}
else
{
result = null;
}
return result;
}
internal Dictionary<short, QSBNetworkMessageDelegate> GetHandlers()
{
return this.m_MsgHandlers;
}
internal void ClearMessageHandlers()
{
this.m_MsgHandlers.Clear();
}
private Dictionary<short, QSBNetworkMessageDelegate> m_MsgHandlers = new Dictionary<short, QSBNetworkMessageDelegate>();
}
}

369
QSB/QSBNetworkScene.cs Normal file
View File

@ -0,0 +1,369 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
namespace QSB
{
class QSBNetworkScene
{
internal Dictionary<NetworkInstanceId, QSBNetworkIdentity> localObjects { get; } = new Dictionary<NetworkInstanceId, QSBNetworkIdentity>();
internal static Dictionary<NetworkHash128, GameObject> guidToPrefab { get; } = new Dictionary<NetworkHash128, GameObject>();
internal static Dictionary<NetworkHash128, SpawnDelegate> spawnHandlers { get; } = new Dictionary<NetworkHash128, SpawnDelegate>();
internal static Dictionary<NetworkHash128, UnSpawnDelegate> unspawnHandlers { get; } = new Dictionary<NetworkHash128, UnSpawnDelegate>();
internal void Shutdown()
{
this.ClearLocalObjects();
ClearSpawners();
}
internal void SetLocalObject(NetworkInstanceId netId, GameObject obj, bool isClient, bool isServer)
{
Debug.Log(string.Concat(new object[]
{
"SetLocalObject ",
netId,
" ",
obj
}));
if (obj == null)
{
this.localObjects[netId] = null;
}
else
{
QSBNetworkIdentity networkIdentity = null;
if (this.localObjects.ContainsKey(netId))
{
networkIdentity = this.localObjects[netId];
}
if (networkIdentity == null)
{
networkIdentity = obj.GetComponent<QSBNetworkIdentity>();
this.localObjects[netId] = networkIdentity;
}
networkIdentity.UpdateClientServer(isClient, isServer);
}
}
internal GameObject FindLocalObject(NetworkInstanceId netId)
{
if (this.localObjects.ContainsKey(netId))
{
QSBNetworkIdentity networkIdentity = this.localObjects[netId];
if (networkIdentity != null)
{
return networkIdentity.gameObject;
}
}
return null;
}
internal bool GetNetworkIdentity(NetworkInstanceId netId, out QSBNetworkIdentity uv)
{
bool result;
if (this.localObjects.ContainsKey(netId) && this.localObjects[netId] != null)
{
uv = this.localObjects[netId];
result = true;
}
else
{
uv = null;
result = false;
}
return result;
}
internal bool RemoveLocalObject(NetworkInstanceId netId)
{
return this.localObjects.Remove(netId);
}
internal bool RemoveLocalObjectAndDestroy(NetworkInstanceId netId)
{
bool result;
if (this.localObjects.ContainsKey(netId))
{
QSBNetworkIdentity networkIdentity = this.localObjects[netId];
UnityEngine.Object.Destroy(networkIdentity.gameObject);
result = this.localObjects.Remove(netId);
}
else
{
result = false;
}
return result;
}
internal void ClearLocalObjects()
{
this.localObjects.Clear();
}
internal static void RegisterPrefab(GameObject prefab, NetworkHash128 newAssetId)
{
QSBNetworkIdentity component = prefab.GetComponent<QSBNetworkIdentity>();
if (component)
{
component.SetDynamicAssetId(newAssetId);
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Registering prefab '",
prefab.name,
"' as asset:",
component.AssetId
}));
}
guidToPrefab[component.AssetId] = prefab;
}
else if (LogFilter.logError)
{
Debug.LogError("Could not register '" + prefab.name + "' since it contains no NetworkIdentity component");
}
}
internal static void RegisterPrefab(GameObject prefab)
{
NetworkIdentity component = prefab.GetComponent<NetworkIdentity>();
if (component)
{
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Registering prefab '",
prefab.name,
"' as asset:",
component.assetId
}));
}
guidToPrefab[component.assetId] = prefab;
NetworkIdentity[] componentsInChildren = prefab.GetComponentsInChildren<NetworkIdentity>();
if (componentsInChildren.Length > 1)
{
if (LogFilter.logWarn)
{
Debug.LogWarning("The prefab '" + prefab.name + "' has multiple NetworkIdentity components. There can only be one NetworkIdentity on a prefab, and it must be on the root object.");
}
}
}
else if (LogFilter.logError)
{
Debug.LogError("Could not register '" + prefab.name + "' since it contains no NetworkIdentity component");
}
}
internal static bool GetPrefab(NetworkHash128 assetId, out GameObject prefab)
{
bool result;
if (!assetId.IsValid())
{
prefab = null;
result = false;
}
else if (guidToPrefab.ContainsKey(assetId) && guidToPrefab[assetId] != null)
{
prefab = guidToPrefab[assetId];
result = true;
}
else
{
prefab = null;
result = false;
}
return result;
}
internal static void ClearSpawners()
{
guidToPrefab.Clear();
spawnHandlers.Clear();
unspawnHandlers.Clear();
}
public static void UnregisterSpawnHandler(NetworkHash128 assetId)
{
spawnHandlers.Remove(assetId);
unspawnHandlers.Remove(assetId);
}
internal static void RegisterSpawnHandler(NetworkHash128 assetId, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
{
if (spawnHandler == null || unspawnHandler == null)
{
if (LogFilter.logError)
{
Debug.LogError("RegisterSpawnHandler custom spawn function null for " + assetId);
}
}
else
{
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"RegisterSpawnHandler asset '",
assetId,
"' ",
spawnHandler.GetMethodName(),
"/",
unspawnHandler.GetMethodName()
}));
}
spawnHandlers[assetId] = spawnHandler;
unspawnHandlers[assetId] = unspawnHandler;
}
}
internal static void UnregisterPrefab(GameObject prefab)
{
NetworkIdentity component = prefab.GetComponent<NetworkIdentity>();
if (component == null)
{
if (LogFilter.logError)
{
Debug.LogError("Could not unregister '" + prefab.name + "' since it contains no NetworkIdentity component");
}
}
else
{
spawnHandlers.Remove(component.assetId);
unspawnHandlers.Remove(component.assetId);
}
}
internal static void RegisterPrefab(GameObject prefab, SpawnDelegate spawnHandler, UnSpawnDelegate unspawnHandler)
{
NetworkIdentity component = prefab.GetComponent<NetworkIdentity>();
if (component == null)
{
if (LogFilter.logError)
{
Debug.LogError("Could not register '" + prefab.name + "' since it contains no NetworkIdentity component");
}
}
else if (spawnHandler == null || unspawnHandler == null)
{
if (LogFilter.logError)
{
Debug.LogError("RegisterPrefab custom spawn function null for " + component.assetId);
}
}
else if (!component.assetId.IsValid())
{
if (LogFilter.logError)
{
Debug.LogError("RegisterPrefab game object " + prefab.name + " has no prefab. Use RegisterSpawnHandler() instead?");
}
}
else
{
if (LogFilter.logDebug)
{
Debug.Log(string.Concat(new object[]
{
"Registering custom prefab '",
prefab.name,
"' as asset:",
component.assetId,
" ",
spawnHandler.GetMethodName(),
"/",
unspawnHandler.GetMethodName()
}));
}
spawnHandlers[component.assetId] = spawnHandler;
unspawnHandlers[component.assetId] = unspawnHandler;
}
}
internal static bool GetSpawnHandler(NetworkHash128 assetId, out SpawnDelegate handler)
{
bool result;
if (spawnHandlers.ContainsKey(assetId))
{
handler = spawnHandlers[assetId];
result = true;
}
else
{
handler = null;
result = false;
}
return result;
}
internal static bool InvokeUnSpawnHandler(NetworkHash128 assetId, GameObject obj)
{
bool result;
if (unspawnHandlers.ContainsKey(assetId) && unspawnHandlers[assetId] != null)
{
UnSpawnDelegate unSpawnDelegate = unspawnHandlers[assetId];
unSpawnDelegate(obj);
result = true;
}
else
{
result = false;
}
return result;
}
internal void DestroyAllClientObjects()
{
foreach (NetworkInstanceId key in this.localObjects.Keys)
{
QSBNetworkIdentity networkIdentity = this.localObjects[key];
if (networkIdentity != null && networkIdentity.gameObject != null)
{
if (!InvokeUnSpawnHandler(networkIdentity.AssetId, networkIdentity.gameObject))
{
if (networkIdentity.SceneId.IsEmpty())
{
UnityEngine.Object.Destroy(networkIdentity.gameObject);
}
else
{
networkIdentity.MarkForReset();
networkIdentity.gameObject.SetActive(false);
}
}
}
}
this.ClearLocalObjects();
}
internal void DumpAllClientObjects()
{
foreach (NetworkInstanceId networkInstanceId in this.localObjects.Keys)
{
QSBNetworkIdentity networkIdentity = this.localObjects[networkInstanceId];
if (networkIdentity != null)
{
Debug.Log(string.Concat(new object[]
{
"ID:",
networkInstanceId,
" OBJ:",
networkIdentity.gameObject,
" AS:",
networkIdentity.AssetId
}));
}
else
{
Debug.Log("ID:" + networkInstanceId + " OBJ: null");
}
}
}
}
}

2197
QSB/QSBNetworkServer.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Networking;
namespace QSB
{
class QSBObjectDestroyMessage : MessageBase
{
public override void Deserialize(NetworkReader reader)
{
netId = reader.ReadNetworkId();
}
public override void Serialize(NetworkWriter writer)
{
writer.Write(netId);
}
public NetworkInstanceId netId;
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Networking;
namespace QSB
{
class QSBObjectSpawnFinishedMessage : MessageBase
{
public override void Deserialize(NetworkReader reader)
{
state = reader.ReadPackedUInt32();
}
public override void Serialize(NetworkWriter writer)
{
writer.WritePackedUInt32(state);
}
public uint state;
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
namespace QSB
{
class QSBObjectSpawnMessage : MessageBase
{
public override void Deserialize(NetworkReader reader)
{
netId = reader.ReadNetworkId();
assetId = reader.ReadNetworkHash128();
position = reader.ReadVector3();
payload = reader.ReadBytesAndSize();
uint num = 16U;
if ((long)reader.Length - (long)((ulong)reader.Position) >= (long)((ulong)num))
{
rotation = reader.ReadQuaternion();
}
}
public override void Serialize(NetworkWriter writer)
{
writer.Write(netId);
writer.Write(assetId);
writer.Write(position);
writer.WriteBytesFull(payload);
writer.Write(rotation);
}
public NetworkInstanceId netId;
public NetworkHash128 assetId;
public Vector3 position;
public byte[] payload;
public Quaternion rotation;
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
namespace QSB
{
class QSBObjectSpawnSceneMessage : MessageBase
{
public override void Deserialize(NetworkReader reader)
{
this.netId = reader.ReadNetworkId();
this.sceneId = reader.ReadSceneId();
this.position = reader.ReadVector3();
this.payload = reader.ReadBytesAndSize();
}
public override void Serialize(NetworkWriter writer)
{
writer.Write(this.netId);
writer.Write(this.sceneId);
writer.Write(this.position);
writer.WriteBytesFull(this.payload);
}
public NetworkInstanceId netId;
public NetworkSceneId sceneId;
public Vector3 position;
public byte[] payload;
}
}

27
QSB/QSBOwnerMessage.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine.Networking;
namespace QSB
{
class QSBOwnerMessage : MessageBase
{
public override void Deserialize(NetworkReader reader)
{
netId = reader.ReadNetworkId();
playerControllerId = (short)reader.ReadPackedUInt32();
}
public override void Serialize(NetworkWriter writer)
{
writer.Write(netId);
writer.WritePackedUInt32((uint)playerControllerId);
}
public NetworkInstanceId netId;
public short playerControllerId;
}
}

View File

@ -0,0 +1,40 @@
using UnityEngine;
namespace QSB
{
public class QSBPlayerController
{
public QSBPlayerController()
{
}
internal QSBPlayerController(GameObject go, short playerControllerId)
{
gameObject = go;
unetView = go.GetComponent<QSBNetworkIdentity>();
this.playerControllerId = playerControllerId;
}
public bool IsValid => playerControllerId != -1;
public override string ToString()
{
return string.Format("ID={0} NetworkIdentity NetID={1} Player={2}", new object[]
{
playerControllerId,
(!(unetView != null)) ? "null" : unetView.NetId.ToString(),
(!(gameObject != null)) ? "null" : gameObject.name
});
}
internal const short kMaxLocalPlayers = 8;
public short playerControllerId = -1;
public QSBNetworkIdentity unetView;
public GameObject gameObject;
public const int MaxPlayersPerClient = 32;
}
}

65
QSB/QSBUtility.cs Normal file
View File

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using UnityEngine.Networking.Types;
namespace QSB
{
public class QSBUtility
{
private QSBUtility()
{
}
[Obsolete("This property is unused and should not be referenced in code.", true)]
public static bool useRandomSourceID
{
get
{
return false;
}
set
{
}
}
public static SourceID GetSourceID()
{
return (SourceID)((long)SystemInfo.deviceUniqueIdentifier.GetHashCode());
}
[Obsolete("This function is unused and should not be referenced in code. Please sign in and setup your project in the editor instead.", true)]
public static void SetAppID(AppID newAppID)
{
}
[Obsolete("This function is unused and should not be referenced in code. Please sign in and setup your project in the editor instead.", true)]
public static AppID GetAppID()
{
return AppID.Invalid;
}
public static void SetAccessTokenForNetwork(NetworkID netId, NetworkAccessToken accessToken)
{
if (s_dictTokens.ContainsKey(netId))
{
s_dictTokens.Remove(netId);
}
s_dictTokens.Add(netId, accessToken);
}
public static NetworkAccessToken GetAccessTokenForNetwork(NetworkID netId)
{
NetworkAccessToken result;
if (!s_dictTokens.TryGetValue(netId, out result))
{
result = new NetworkAccessToken();
}
return result;
}
private static Dictionary<NetworkID, NetworkAccessToken> s_dictTokens = new Dictionary<NetworkID, NetworkAccessToken>();
}
}