示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#4
0
        /// <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);
                }
        }
示例#8
0
        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();
            }
        }
示例#11
0
 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);
         }
     }
 }
示例#12
0
 /// <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);
                }
        }
示例#17
0
        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);
                }
        }
示例#20
0
        /// <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()));
                }
        }
示例#22
0
        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);
                        }
                    }
                }
            }
        }
示例#23
0
 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);
             }
         }
     }
 }
示例#24
0
        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);
                }
        }
示例#26
0
        /// <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();
                    }
                }
            }
        }
示例#29
0
        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);
            }
        }
示例#30
0
        // 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);
            }
        }