internal static void SendSpawnCallForObject(ulong clientId, NetworkObject networkObject, Stream payload) { //Currently, if this is called and the clientId (destination) is the server's client Id, this case //will be checked within the below Send function. To avoid unwarranted allocation of a PooledNetworkBuffer //placing this check here. [NSS] if (NetworkManager.Singleton.IsServer && clientId == NetworkManager.Singleton.ServerClientId) { return; } var rpcQueueContainer = NetworkManager.Singleton.RpcQueueContainer; var buffer = PooledNetworkBuffer.Get(); WriteSpawnCallForObject(buffer, clientId, networkObject, payload); var queueItem = new RpcFrameQueueItem { UpdateStage = NetworkUpdateStage.Update, QueueItemType = RpcQueueContainer.QueueItemType.CreateObject, NetworkId = 0, NetworkBuffer = buffer, NetworkChannel = NetworkChannel.Internal, ClientNetworkIds = new[] { clientId } }; rpcQueueContainer.AddToInternalMLAPISendQueue(queueItem); }
private void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStream) { var networkObjects = UnityEngine.Object.FindObjectsOfType <NetworkObject>(); m_NetworkManager.SpawnManager.ClientCollectSoftSyncSceneObjectSweep(networkObjects); using (var reader = PooledNetworkReader.Get(objectStream)) { var newObjectsCount = reader.ReadUInt32Packed(); for (int i = 0; i < newObjectsCount; i++) { NetworkObject.DeserializeSceneObject(objectStream as Serialization.NetworkBuffer, reader, m_NetworkManager); } } using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteByteArray(switchSceneGuid.ToByteArray()); m_NetworkManager.MessageSender.Send(m_NetworkManager.ServerClientId, NetworkConstants.CLIENT_SWITCH_SCENE_COMPLETED, NetworkChannel.Internal, buffer); } s_IsSwitching = false; OnSceneSwitched?.Invoke(); }
/// <summary> /// Should be called the first time a queue item is pulled from a queue history frame. /// This will reset the frame's stream indices and add a new stream and stream writer to the m_CurrentQueueItem instance. /// </summary> /// <returns>FrameQueueItem</returns> internal RpcFrameQueueItem GetFirstQueueItem() { if (QueueBuffer.Position > 0) { m_QueueItemOffsetIndex = 0; QueueBuffer.Position = 0; if (m_QueueFrameType == QueueFrameType.Inbound) { if (m_CurrentQueueItem.NetworkBuffer == null) { m_CurrentQueueItem.NetworkBuffer = PooledNetworkBuffer.Get(); } if (m_CurrentQueueItem.NetworkWriter == null) { m_CurrentQueueItem.NetworkWriter = PooledNetworkWriter.Get(m_CurrentQueueItem.NetworkBuffer); } if (m_CurrentQueueItem.NetworkReader == null) { m_CurrentQueueItem.NetworkReader = PooledNetworkReader.Get(m_CurrentQueueItem.NetworkBuffer); } } return(GetCurrentQueueItem()); } m_CurrentQueueItem.QueueItemType = RpcQueueContainer.QueueItemType.None; return(m_CurrentQueueItem); }
/// <summary> /// Hides a object from a specific client /// </summary> /// <param name="clientId">The client to hide the object for</param> public void NetworkHide(ulong clientId) { if (!IsSpawned) { throw new SpawnStateException("Object is not spawned"); } if (!NetworkManager.Singleton.IsServer) { throw new NotServerException("Only server can change visibility"); } if (!m_Observers.Contains(clientId)) { throw new VisibilityChangeException("The object is already hidden"); } if (clientId == NetworkManager.Singleton.ServerClientId) { throw new VisibilityChangeException("Cannot hide an object from the server"); } // Send destroy call m_Observers.Remove(clientId); using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt64Packed(NetworkObjectId); InternalMessageSender.Send(clientId, NetworkConstants.DESTROY_OBJECT, NetworkChannel.Internal, buffer); } }
internal void RemoveOwnership(NetworkObject networkObject) { if (!NetworkManager.IsServer) { throw new NotServerException("Only the server can change ownership"); } if (!networkObject.IsSpawned) { throw new SpawnStateException("Object is not spawned"); } for (int i = NetworkManager.ConnectedClients[networkObject.OwnerClientId].OwnedObjects.Count - 1; i > -1; i--) { if (NetworkManager.ConnectedClients[networkObject.OwnerClientId].OwnedObjects[i] == networkObject) { NetworkManager.ConnectedClients[networkObject.OwnerClientId].OwnedObjects.RemoveAt(i); } } networkObject.OwnerClientIdInternal = null; using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt64Packed(networkObject.NetworkObjectId); writer.WriteUInt64Packed(networkObject.OwnerClientId); NetworkManager.MessageSender.Send(NetworkConstants.CHANGE_OWNER, NetworkChannel.Internal, buffer); } }
private static void LogServer(string message, LogType logType) { // Get the sender of the local log ulong localId = NetworkManager.Singleton != null ? NetworkManager.Singleton.LocalClientId : 0; switch (logType) { case LogType.Info: LogInfoServerLocal(message, localId); break; case LogType.Warning: LogWarningServerLocal(message, localId); break; case LogType.Error: LogErrorServerLocal(message, localId); break; } if (NetworkManager.Singleton != null && !NetworkManager.Singleton.IsServer && NetworkManager.Singleton.NetworkConfig.EnableNetworkLogs) { using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteByte((byte)logType); writer.WriteStringPacked(message); NetworkManager.Singleton.MessageSender.Send(NetworkManager.Singleton.ServerClientId, NetworkConstants.SERVER_LOG, NetworkChannel.Internal, buffer); } } }
/// <summary> /// Sends a named message /// </summary> /// <param name="name">The message name to send</param> /// <param name="clientId">The client to send the message to</param> /// <param name="stream">The message stream containing the data</param> /// <param name="networkChannel">The channel to send the data on</param> public static void SendNamedMessage(string name, ulong clientId, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal) { ulong hash = 0; switch (NetworkManager.Singleton.NetworkConfig.RpcHashSize) { case HashSize.VarIntTwoBytes: hash = name.GetStableHash16(); break; case HashSize.VarIntFourBytes: hash = name.GetStableHash32(); break; case HashSize.VarIntEightBytes: hash = name.GetStableHash64(); break; } using (var messageBuffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(messageBuffer)) { writer.WriteUInt64Packed(hash); messageBuffer.CopyFrom(stream); InternalMessageSender.Send(clientId, NetworkConstants.NAMED_MESSAGE, networkChannel, messageBuffer); PerformanceDataManager.Increment(ProfilerConstants.NamedMessageSent); } }
internal static void ChangeOwnership(NetworkObject networkObject, ulong clientId) { if (!NetworkManager.Singleton.IsServer) { throw new NotServerException("Only the server can change ownership"); } if (!networkObject.IsSpawned) { throw new SpawnStateException("Object is not spawned"); } if (NetworkManager.Singleton.ConnectedClients.ContainsKey(networkObject.OwnerClientId)) { for (int i = NetworkManager.Singleton.ConnectedClients[networkObject.OwnerClientId].OwnedObjects.Count - 1; i >= 0; i--) { if (NetworkManager.Singleton.ConnectedClients[networkObject.OwnerClientId].OwnedObjects[i] == networkObject) { NetworkManager.Singleton.ConnectedClients[networkObject.OwnerClientId].OwnedObjects.RemoveAt(i); } } } NetworkManager.Singleton.ConnectedClients[clientId].OwnedObjects.Add(networkObject); networkObject.OwnerClientId = clientId; using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt64Packed(networkObject.NetworkObjectId); writer.WriteUInt64Packed(clientId); InternalMessageSender.Send(NetworkConstants.CHANGE_OWNER, NetworkChannel.Internal, buffer); } }
internal static void OnFirstSceneSwitchSync(uint sceneIndex, Guid switchSceneGuid) { if (!SceneIndexToString.ContainsKey(sceneIndex) || !RegisteredSceneNames.Contains(SceneIndexToString[sceneIndex])) { if (NetworkLog.CurrentLogLevel <= LogLevel.Normal) { NetworkLog.LogWarning("Server requested a scene switch to a non-registered scene"); } return; } if (SceneManager.GetActiveScene().name == SceneIndexToString[sceneIndex]) { return; //This scene is already loaded. This usually happends at first load } s_LastScene = SceneManager.GetActiveScene(); string sceneName = SceneIndexToString[sceneIndex]; s_NextSceneName = sceneName; CurrentActiveSceneIndex = SceneNameToIndex[sceneName]; IsSpawnedObjectsPendingInDontDestroyOnLoad = true; SceneManager.LoadScene(sceneName); using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteByteArray(switchSceneGuid.ToByteArray()); InternalMessageSender.Send(NetworkManager.Singleton.ServerClientId, NetworkConstants.CLIENT_SWITCH_SCENE_COMPLETED, NetworkChannel.Internal, buffer); } s_IsSwitching = false; }
/// <summary> /// Initialize /// This should be called during primary initialization period (typically during NetworkManager's Start method) /// This will allocate [maxFrameHistory] + [1 currentFrame] number of PooledNetworkBuffers and keep them open until the session ends /// Note: For zero frame history set maxFrameHistory to zero /// </summary> /// <param name="maxFrameHistory"></param> public void Initialize(uint maxFrameHistory) { ClearParameters(); m_RpcQueueProcessor = new RpcQueueProcessor(); m_MaxFrameHistory = maxFrameHistory + k_MinQueueHistory; if (!QueueHistory.ContainsKey(RpcQueueHistoryFrame.QueueFrameType.Inbound)) { QueueHistory.Add(RpcQueueHistoryFrame.QueueFrameType.Inbound, new Dictionary <int, Dictionary <NetworkUpdateStage, RpcQueueHistoryFrame> >()); } if (!QueueHistory.ContainsKey(RpcQueueHistoryFrame.QueueFrameType.Outbound)) { QueueHistory.Add(RpcQueueHistoryFrame.QueueFrameType.Outbound, new Dictionary <int, Dictionary <NetworkUpdateStage, RpcQueueHistoryFrame> >()); } for (int i = 0; i < m_MaxFrameHistory; i++) { if (!QueueHistory[RpcQueueHistoryFrame.QueueFrameType.Outbound].ContainsKey(i)) { QueueHistory[RpcQueueHistoryFrame.QueueFrameType.Outbound].Add(i, new Dictionary <NetworkUpdateStage, RpcQueueHistoryFrame>()); var queueHistoryFrame = new RpcQueueHistoryFrame(RpcQueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); queueHistoryFrame.QueueBuffer = PooledNetworkBuffer.Get(); queueHistoryFrame.QueueBuffer.Position = 0; queueHistoryFrame.QueueWriter = PooledNetworkWriter.Get(queueHistoryFrame.QueueBuffer); queueHistoryFrame.QueueReader = PooledNetworkReader.Get(queueHistoryFrame.QueueBuffer); queueHistoryFrame.QueueItemOffsets = new List <uint>(); //For now all outbound, we will always have a single update in which they are processed (LATEUPDATE) QueueHistory[RpcQueueHistoryFrame.QueueFrameType.Outbound][i].Add(NetworkUpdateStage.PostLateUpdate, queueHistoryFrame); } if (!QueueHistory[RpcQueueHistoryFrame.QueueFrameType.Inbound].ContainsKey(i)) { QueueHistory[RpcQueueHistoryFrame.QueueFrameType.Inbound].Add(i, new Dictionary <NetworkUpdateStage, RpcQueueHistoryFrame>()); //For inbound, we create a queue history frame per update stage foreach (NetworkUpdateStage netUpdateStage in Enum.GetValues(typeof(NetworkUpdateStage))) { var rpcQueueHistoryFrame = new RpcQueueHistoryFrame(RpcQueueHistoryFrame.QueueFrameType.Inbound, netUpdateStage); rpcQueueHistoryFrame.QueueBuffer = PooledNetworkBuffer.Get(); rpcQueueHistoryFrame.QueueBuffer.Position = 0; rpcQueueHistoryFrame.QueueWriter = PooledNetworkWriter.Get(rpcQueueHistoryFrame.QueueBuffer); rpcQueueHistoryFrame.QueueReader = PooledNetworkReader.Get(rpcQueueHistoryFrame.QueueBuffer); rpcQueueHistoryFrame.QueueItemOffsets = new List <uint>(); QueueHistory[RpcQueueHistoryFrame.QueueFrameType.Inbound][i].Add(netUpdateStage, rpcQueueHistoryFrame); } } } //As long as this instance is using the pre-defined update stages if (!m_ProcessUpdateStagesExternally) { //Register with the network update loop system this.RegisterAllNetworkUpdates(); } }
private void SendNetMessage(string msg_name, string msg) { print("Sending net message"); using (var buffer = PooledNetworkBuffer.Get()) { using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteString(msg); MLAPI.Messaging.CustomMessagingManager.SendNamedMessage( msg_name, null, buffer); } } }
/// <summary> /// Responsible for the Server->Client RPC's of the connection result. /// </summary> /// <param name="netId"> id of the client to send to </param> /// <param name="status"> the status to pass to the client</param> public void S2CConnectResult(ulong netId, ConnectStatus status) { using (var buffer = PooledNetworkBuffer.Get()) { using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteInt32((int)status); MLAPI.Messaging.CustomMessagingManager.SendNamedMessage("S2C_ConnectResult", netId, buffer, NetworkChannel.Internal); } } }
public void SendPlayerEjectionCommand(string userId) { using (PooledNetworkBuffer stream = PooledNetworkBuffer.Get()) { using (PooledNetworkWriter writer = PooledNetworkWriter.Get(stream)) { writer.WriteStringPacked(userId); _Client.SendMessageToServer(GameRoomMessagingHubConstants.SEND_PLAYER_EJECTION_COMMAND, stream); } } }
public void SendSystemUserIdToServer(string userId) { using (PooledNetworkBuffer stream = PooledNetworkBuffer.Get()) { using (PooledNetworkWriter writer = PooledNetworkWriter.Get(stream)) { writer.WriteStringPacked(userId); _Client.SendMessageToServer(GameRoomMessagingHubConstants.SEND_SYSTEM_USERID_TO_SERVER, stream); } } }
public void SendServerProcessDownCommand(int timeSeconds) { using (PooledNetworkBuffer stream = PooledNetworkBuffer.Get()) { using (PooledNetworkWriter writer = PooledNetworkWriter.Get(stream)) { writer.WriteInt32Packed(timeSeconds); _Client.SendMessageToServer(GameRoomMessagingHubConstants.SEND_SERVER_PROCESS_DOWN_COMMAND, stream); } } }
/// <summary> /// Hides a list of objects from a client /// </summary> /// <param name="networkObjects">The objects to hide</param> /// <param name="clientId">The client to hide the objects from</param> public static void NetworkHide(List <NetworkObject> networkObjects, ulong clientId) { if (networkObjects == null || networkObjects.Count == 0) { throw new ArgumentNullException("At least one " + nameof(NetworkObject) + " has to be provided"); } NetworkManager networkManager = networkObjects[0].NetworkManager; if (!networkManager.IsServer) { throw new NotServerException("Only server can change visibility"); } if (clientId == networkManager.ServerClientId) { throw new VisibilityChangeException("Cannot hide an object from the server"); } // Do the safety loop first to prevent putting the MLAPI in an invalid state. for (int i = 0; i < networkObjects.Count; i++) { if (!networkObjects[i].IsSpawned) { throw new SpawnStateException("Object is not spawned"); } if (!networkObjects[i].Observers.Contains(clientId)) { throw new VisibilityChangeException($"{nameof(NetworkObject)} with {nameof(NetworkObjectId)}: {networkObjects[i].NetworkObjectId} is already hidden"); } if (networkObjects[i].NetworkManager != networkManager) { throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(NetworkManager)); } } using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt16Packed((ushort)networkObjects.Count); for (int i = 0; i < networkObjects.Count; i++) { // Send destroy call networkObjects[i].Observers.Remove(clientId); writer.WriteUInt64Packed(networkObjects[i].NetworkObjectId); } networkManager.MessageSender.Send(clientId, NetworkConstants.DESTROY_OBJECTS, NetworkChannel.Internal, buffer); } }
internal static NetworkBuffer WrapMessage(byte messageType, NetworkBuffer messageBody) { var outStream = PooledNetworkBuffer.Get(); using (var outWriter = PooledNetworkWriter.Get(outStream)) { outWriter.WriteByte(messageType); outStream.Write(messageBody.GetBuffer(), 0, (int)messageBody.Length); } return(outStream); }
// todo --M1-- // for now, the full snapshot is always sent // this will change significantly /// <summary> /// Send the snapshot to a specific client /// </summary> /// <param name="clientId">The client index to send to</param> private void SendSnapshot(ulong clientId) { // Send the entry index and the buffer where the variables are serialized using (var buffer = PooledNetworkBuffer.Get()) { WriteIndex(buffer); WriteBuffer(buffer); m_NetworkManager.MessageSender.Send(clientId, NetworkConstants.SNAPSHOT_DATA, NetworkChannel.SnapshotExchange, buffer); buffer.Dispose(); } }
/// <summary> /// Shows a list of previously hidden objects to a client /// </summary> /// <param name="networkObjects">The objects to show</param> /// <param name="clientId">The client to show the objects to</param> /// <param name="payload">An optional payload to send as part of the spawns</param> public static void NetworkShow(List <NetworkObject> networkObjects, ulong clientId, Stream payload = null) { if (networkObjects == null || networkObjects.Count == 0) { throw new ArgumentNullException("At least one " + nameof(NetworkObject) + " has to be provided"); } NetworkManager networkManager = networkObjects[0].NetworkManager; if (!networkManager.IsServer) { throw new NotServerException("Only server can change visibility"); } // Do the safety loop first to prevent putting the MLAPI in an invalid state. for (int i = 0; i < networkObjects.Count; i++) { if (!networkObjects[i].IsSpawned) { throw new SpawnStateException("Object is not spawned"); } if (networkObjects[i].Observers.Contains(clientId)) { throw new VisibilityChangeException($"{nameof(NetworkObject)} with NetworkId: {networkObjects[i].NetworkObjectId} is already visible"); } if (networkObjects[i].NetworkManager != networkManager) { throw new ArgumentNullException("All " + nameof(NetworkObject) + "s must belong to the same " + nameof(NetworkManager)); } } using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt16Packed((ushort)networkObjects.Count); for (int i = 0; i < networkObjects.Count; i++) { // Send spawn call networkObjects[i].Observers.Add(clientId); networkManager.SpawnManager.WriteSpawnCallForObject(buffer, clientId, networkObjects[i], payload); } networkManager.MessageSender.Send(clientId, NetworkConstants.ADD_OBJECTS, NetworkChannel.Internal, buffer); } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkConfig instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (m_ConfigHash != null && cache) { return(m_ConfigHash.Value); } Sort(); using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(NetworkConstants.PROTOCOL_VERSION); if (EnableSceneManagement && !AllowRuntimeSceneChanges) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (ForceSamePrefabs) { var sortedPrefabList = NetworkPrefabs.OrderBy(x => x.Hash).ToList(); for (int i = 0; i < sortedPrefabList.Count; i++) { writer.WriteUInt64Packed(sortedPrefabList[i].Hash); } } writer.WriteBool(EnableNetworkVariable); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(EnsureNetworkVariableLengthSafety); writer.WriteBits((byte)RpcHashSize, 2); buffer.PadBuffer(); if (cache) { m_ConfigHash = buffer.ToArray().GetStableHash64(); return(m_ConfigHash.Value); } return(buffer.ToArray().GetStableHash64()); } }
/// <summary> /// Gets a SHA256 hash of parts of the NetworkConfig instance /// </summary> /// <param name="cache"></param> /// <returns></returns> public ulong GetConfig(bool cache = true) { if (m_ConfigHash != null && cache) { return(m_ConfigHash.Value); } Sort(); using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt16Packed(ProtocolVersion); writer.WriteString(NetworkConstants.PROTOCOL_VERSION); if (EnableSceneManagement && !AllowRuntimeSceneChanges) { for (int i = 0; i < RegisteredScenes.Count; i++) { writer.WriteString(RegisteredScenes[i]); } } if (ForceSamePrefabs) { var sortedDictionary = NetworkPrefabOverrideLinks.OrderBy(x => x.Key); foreach (var sortedEntry in sortedDictionary) { writer.WriteUInt32Packed(sortedEntry.Key); } } writer.WriteBool(EnableNetworkVariable); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(EnableSceneManagement); writer.WriteBool(EnsureNetworkVariableLengthSafety); writer.WriteBits((byte)RpcHashSize, 2); buffer.PadBuffer(); if (cache) { m_ConfigHash = XXHash.Hash64(buffer.ToArray()); return(m_ConfigHash.Value); } return(XXHash.Hash64(buffer.ToArray())); } }
internal static void WriteNetworkVariableData(List <INetworkVariable> networkVariableList, Stream stream, ulong clientId, NetworkManager networkManager) { if (networkVariableList.Count == 0) { return; } using (var writer = PooledNetworkWriter.Get(stream)) { for (int j = 0; j < networkVariableList.Count; j++) { bool canClientRead = networkVariableList[j].CanClientRead(clientId); if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) { if (!canClientRead) { writer.WriteUInt16Packed(0); } } else { writer.WriteBool(canClientRead); } if (canClientRead) { if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety) { using (var varBuffer = PooledNetworkBuffer.Get()) { networkVariableList[j].WriteField(varBuffer); varBuffer.PadBuffer(); writer.WriteUInt16Packed((ushort)varBuffer.Length); varBuffer.CopyTo(stream); } } else { networkVariableList[j].WriteField(stream); } } } } }
public void C2SSceneChanged(int newScene) { if (NetManager.IsHost) { ClientSceneChanged?.Invoke(NetManager.ServerClientId, newScene); } else if (NetManager.IsConnectedClient) { using (var buffer = PooledNetworkBuffer.Get()) { using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteInt32(newScene); MLAPI.Messaging.CustomMessagingManager.SendNamedMessage("C2S_SceneChanged", NetManager.ServerClientId, buffer, NetworkChannel.Internal); } } } }
public void StartGame() { var pts = new HashSet <Transform>(_SpawnPoints.GetComponentsInChildren <Transform>()); pts.Remove(_SpawnPoints.transform); // Why does unity return parent also ? foreach (var(player, point) in _SessionManager.Zip(pts, (player, point) => (player, point.localPosition))) { var obj = Instantiate(_PlayerPrefab, point, Quaternion.identity); using var stream = PooledNetworkBuffer.Get(); using var writer = PooledNetworkWriter.Get(stream); writer.WriteByte((byte)player.Character); writer.WritePadBits(); var net = obj.GetComponent <NetworkObject>(); net.SpawnAsPlayerObject(player.ID, stream, true); } }
/// <summary> /// Sends the named message /// </summary> /// <param name="name">The message name to send</param> /// <param name="clientIds">The clients to send to, sends to everyone if null</param> /// <param name="stream">The message stream containing the data</param> /// <param name="networkChannel">The channel to send the data on</param> public static void SendNamedMessage(string name, List <ulong> clientIds, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal) { ulong hash = 0; switch (NetworkManager.Singleton.NetworkConfig.RpcHashSize) { case HashSize.VarIntTwoBytes: hash = name.GetStableHash16(); break; case HashSize.VarIntFourBytes: hash = name.GetStableHash32(); break; case HashSize.VarIntEightBytes: hash = name.GetStableHash64(); break; } using (var messageBuffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(messageBuffer)) { writer.WriteUInt64Packed(hash); messageBuffer.CopyFrom(stream); if (!NetworkManager.Singleton.IsServer) { if (NetworkLog.CurrentLogLevel <= LogLevel.Error) { NetworkLog.LogWarning("Can not send named messages to multiple users as a client"); } return; } InternalMessageSender.Send(NetworkConstants.NAMED_MESSAGE, networkChannel, clientIds, messageBuffer); PerformanceDataManager.Increment(ProfilerConstants.NamedMessageSent); } }
/// <summary> /// Returns a base64 encoded version of the config /// </summary> /// <returns></returns> public string ToBase64() { NetworkConfig config = this; using (var buffer = PooledNetworkBuffer.Get()) using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt16Packed(config.ProtocolVersion); writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count); for (int i = 0; i < config.RegisteredScenes.Count; i++) { writer.WriteString(config.RegisteredScenes[i]); } writer.WriteInt32Packed(config.ReceiveTickrate); writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate); writer.WriteInt32Packed(config.EventTickrate); writer.WriteInt32Packed(config.ClientConnectionBufferTimeout); writer.WriteBool(config.ConnectionApproval); writer.WriteInt32Packed(config.SecondsHistory); writer.WriteInt32Packed(config.LoadSceneTimeOut); writer.WriteBool(config.EnableTimeResync); writer.WriteBool(config.EnsureNetworkVariableLengthSafety); writer.WriteBits((byte)config.RpcHashSize, 2); writer.WriteBool(ForceSamePrefabs); writer.WriteBool(UsePrefabSync); writer.WriteBool(EnableSceneManagement); writer.WriteBool(RecycleNetworkIds); writer.WriteSinglePacked(NetworkIdRecycleDelay); writer.WriteBool(EnableNetworkVariable); writer.WriteBool(AllowRuntimeSceneChanges); writer.WriteBool(EnableNetworkLogs); buffer.PadBuffer(); return(Convert.ToBase64String(buffer.ToArray())); } }
internal static void BufferMessageForNetworkId(ulong networkId, ulong senderClientId, NetworkChannel networkChannel, float receiveTime, ArraySegment <byte> payload) { if (!s_BufferQueues.ContainsKey(networkId)) { s_BufferQueues.Add(networkId, new Queue <BufferedMessage>()); } Queue <BufferedMessage> queue = s_BufferQueues[networkId]; var payloadBuffer = PooledNetworkBuffer.Get(); payloadBuffer.Write(payload.Array, payload.Offset, payload.Count); payloadBuffer.Position = 0; queue.Enqueue(new BufferedMessage() { BufferTime = Time.realtimeSinceStartup, NetworkChannel = networkChannel, NetworkBuffer = payloadBuffer, ReceiveTime = receiveTime, SenderClientId = senderClientId }); }
/// <summary> /// LoopbackSendFrame /// Will copy the contents of the current outbound QueueHistoryFrame to the current inbound QueueHistoryFrame /// [NSS]: Leaving this here in the event a portion of this code is useful for doing Batch testing /// </summary> public void LoopbackSendFrame() { //If we do not have loop back or testing mode enabled then ignore the call if (m_IsTestingEnabled) { var rpcQueueHistoryItemOutbound = GetQueueHistoryFrame(RpcQueueHistoryFrame.QueueFrameType.Outbound, NetworkUpdateStage.PostLateUpdate); if (rpcQueueHistoryItemOutbound.QueueItemOffsets.Count > 0) { //Reset inbound queues based on update stage foreach (NetworkUpdateStage netUpdateStage in Enum.GetValues(typeof(NetworkUpdateStage))) { var rpcQueueHistoryItemInbound = GetQueueHistoryFrame(RpcQueueHistoryFrame.QueueFrameType.Inbound, netUpdateStage); ResetQueueHistoryFrame(rpcQueueHistoryItemInbound); } var pooledNetworkBuffer = PooledNetworkBuffer.Get(); var rpcFrameQueueItem = rpcQueueHistoryItemOutbound.GetFirstQueueItem(); while (rpcFrameQueueItem.QueueItemType != QueueItemType.None) { pooledNetworkBuffer.SetLength(rpcFrameQueueItem.StreamSize); pooledNetworkBuffer.Position = 0; byte[] pooledNetworkStreamArray = pooledNetworkBuffer.GetBuffer(); Buffer.BlockCopy(rpcFrameQueueItem.MessageData.Array ?? Array.Empty <byte>(), rpcFrameQueueItem.MessageData.Offset, pooledNetworkStreamArray, 0, (int)rpcFrameQueueItem.StreamSize); if (!IsUsingBatching()) { pooledNetworkBuffer.Position = 1; } AddQueueItemToInboundFrame(rpcFrameQueueItem.QueueItemType, UnityEngine.Time.realtimeSinceStartup, rpcFrameQueueItem.NetworkId, pooledNetworkBuffer); rpcFrameQueueItem = rpcQueueHistoryItemOutbound.GetNextQueueItem(); } } } }
internal static void OnDestroyObject(ulong networkId, bool destroyGameObject) { if (ReferenceEquals(NetworkManager.Singleton, null)) { return; } //Removal of spawned object if (!SpawnedObjects.ContainsKey(networkId)) { Debug.LogWarning($"Trying to destroy object {networkId} but it doesn't seem to exist anymore!"); return; } var sobj = SpawnedObjects[networkId]; if (!sobj.IsOwnedByServer && !sobj.IsPlayerObject && NetworkManager.Singleton.ConnectedClients.ContainsKey(sobj.OwnerClientId)) { //Someone owns it. for (int i = NetworkManager.Singleton.ConnectedClients[sobj.OwnerClientId].OwnedObjects.Count - 1; i > -1; i--) { if (NetworkManager.Singleton.ConnectedClients[sobj.OwnerClientId].OwnedObjects[i].NetworkObjectId == networkId) { NetworkManager.Singleton.ConnectedClients[sobj.OwnerClientId].OwnedObjects.RemoveAt(i); } } } sobj.IsSpawned = false; if (NetworkManager.Singleton != null && NetworkManager.Singleton.IsServer) { if (NetworkManager.Singleton.NetworkConfig.RecycleNetworkIds) { ReleasedNetworkObjectIds.Enqueue(new ReleasedNetworkId() { NetworkId = networkId, ReleaseTime = Time.unscaledTime }); } var rpcQueueContainer = NetworkManager.Singleton.RpcQueueContainer; if (rpcQueueContainer != null) { if (!ReferenceEquals(sobj, null)) { // As long as we have any remaining clients, then notify of the object being destroy. if (NetworkManager.Singleton.ConnectedClientsList.Count > 0) { var buffer = PooledNetworkBuffer.Get(); using (var writer = PooledNetworkWriter.Get(buffer)) { writer.WriteUInt64Packed(networkId); var queueItem = new RpcFrameQueueItem { UpdateStage = NetworkUpdateStage.PostLateUpdate, QueueItemType = RpcQueueContainer.QueueItemType.DestroyObject, NetworkId = networkId, NetworkBuffer = buffer, NetworkChannel = NetworkChannel.Internal, ClientNetworkIds = NetworkManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray() }; rpcQueueContainer.AddToInternalMLAPISendQueue(queueItem); } } } } } var gobj = sobj.gameObject; if (destroyGameObject && !ReferenceEquals(gobj, null)) { if (CustomDestroyHandlers.ContainsKey(sobj.PrefabHash)) { CustomDestroyHandlers[sobj.PrefabHash](sobj); OnDestroyObject(networkId, false); } else { MonoBehaviour.Destroy(gobj); } } // for some reason, we can get down here and SpawnedObjects for this // networkId will no longer be here, even as we check this at the start // of the function if (SpawnedObjects.ContainsKey(networkId)) { SpawnedObjectsList.Remove(sobj); SpawnedObjects.Remove(networkId); } }
// Ran on both server and client internal static void SpawnNetworkObjectLocally(NetworkObject networkObject, ulong networkId, bool sceneObject, bool playerObject, ulong?ownerClientId, Stream dataStream, bool readPayload, int payloadLength, bool readNetworkVariable, bool destroyWithScene) { if (ReferenceEquals(networkObject, null)) { throw new ArgumentNullException(nameof(networkObject), "Cannot spawn null object"); } if (networkObject.IsSpawned) { throw new SpawnStateException("Object is already spawned"); } if (readNetworkVariable && NetworkManager.Singleton.NetworkConfig.EnableNetworkVariable) { networkObject.SetNetworkVariableData(dataStream); } if (SpawnedObjects.ContainsKey(networkObject.NetworkObjectId)) { return; } networkObject.IsSpawned = true; networkObject.IsSceneObject = sceneObject; networkObject.NetworkObjectId = networkId; networkObject.DestroyWithScene = sceneObject || destroyWithScene; networkObject.OwnerClientIdInternal = ownerClientId; networkObject.IsPlayerObject = playerObject; SpawnedObjects.Add(networkObject.NetworkObjectId, networkObject); SpawnedObjectsList.Add(networkObject); if (ownerClientId != null) { if (NetworkManager.Singleton.IsServer) { if (playerObject) { NetworkManager.Singleton.ConnectedClients[ownerClientId.Value].PlayerObject = networkObject; } else { NetworkManager.Singleton.ConnectedClients[ownerClientId.Value].OwnedObjects.Add(networkObject); } } else if (playerObject && ownerClientId.Value == NetworkManager.Singleton.LocalClientId) { NetworkManager.Singleton.ConnectedClients[ownerClientId.Value].PlayerObject = networkObject; } } if (NetworkManager.Singleton.IsServer) { for (int i = 0; i < NetworkManager.Singleton.ConnectedClientsList.Count; i++) { if (networkObject.CheckObjectVisibility == null || networkObject.CheckObjectVisibility(NetworkManager.Singleton.ConnectedClientsList[i].ClientId)) { networkObject.m_Observers.Add(NetworkManager.Singleton.ConnectedClientsList[i].ClientId); } } } networkObject.ResetNetworkStartInvoked(); if (readPayload) { using (var payloadBuffer = PooledNetworkBuffer.Get()) { payloadBuffer.CopyUnreadFrom(dataStream, payloadLength); dataStream.Position += payloadLength; payloadBuffer.Position = 0; networkObject.InvokeBehaviourNetworkSpawn(payloadBuffer); } } else { networkObject.InvokeBehaviourNetworkSpawn(null); } }