示例#1
0
        internal static BitStream WrapMessage(byte messageType, ulong clientId, BitStream messageBody, SecuritySendFlags flags)
        {
            try
            {
                bool encrypted     = ((flags & SecuritySendFlags.Encrypted) == SecuritySendFlags.Encrypted) && NetworkingManager.Singleton.NetworkConfig.EnableEncryption;
                bool authenticated = (flags & SecuritySendFlags.Authenticated) == SecuritySendFlags.Authenticated && NetworkingManager.Singleton.NetworkConfig.EnableEncryption;

                PooledBitStream outStream = PooledBitStream.Get();

                using (PooledBitWriter outWriter = PooledBitWriter.Get(outStream))
                {
                    outWriter.WriteBit(encrypted);
                    outWriter.WriteBit(authenticated);

#if !DISABLE_CRYPTOGRAPHY
                    if (authenticated || encrypted)
                    {
                        outWriter.WritePadBits();
                        long hmacWritePos = outStream.Position;

                        if (authenticated)
                        {
                            outStream.Write(HMAC_PLACEHOLDER, 0, HMAC_PLACEHOLDER.Length);
                        }

                        if (encrypted)
                        {
                            using (RijndaelManaged rijndael = new RijndaelManaged())
                            {
                                rijndael.GenerateIV();
                                rijndael.Padding = PaddingMode.PKCS7;

                                byte[] key = NetworkingManager.Singleton.IsServer ? CryptographyHelper.GetClientKey(clientId) : CryptographyHelper.GetServerKey();

                                if (key == null)
                                {
                                    if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                                    {
                                        NetworkLog.LogError("Failed to grab key");
                                    }
                                    return(null);
                                }

                                rijndael.Key = key;

                                outStream.Write(rijndael.IV);

                                using (CryptoStream encryptionStream = new CryptoStream(outStream, rijndael.CreateEncryptor(), CryptoStreamMode.Write))
                                {
                                    encryptionStream.WriteByte(messageType);
                                    encryptionStream.Write(messageBody.GetBuffer(), 0, (int)messageBody.Length);
                                }
                            }
                        }
                        else
                        {
                            outStream.WriteByte(messageType);
                            outStream.Write(messageBody.GetBuffer(), 0, (int)messageBody.Length);
                        }

                        if (authenticated)
                        {
                            byte[] key = NetworkingManager.Singleton.IsServer ? CryptographyHelper.GetClientKey(clientId) : CryptographyHelper.GetServerKey();

                            if (key == null)
                            {
                                if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                                {
                                    NetworkLog.LogError("Failed to grab key");
                                }
                                return(null);
                            }

                            using (HMACSHA256 hmac = new HMACSHA256(key))
                            {
                                byte[] computedHmac = hmac.ComputeHash(outStream.GetBuffer(), 0, (int)outStream.Length);

                                outStream.Position = hmacWritePos;
                                outStream.Write(computedHmac, 0, computedHmac.Length);
                            }
                        }
                    }
                    else
                    {
#endif
                    outWriter.WriteBits(messageType, 6);
                    outStream.Write(messageBody.GetBuffer(), 0, (int)messageBody.Length);
#if !DISABLE_CRYPTOGRAPHY
                }
#endif
                }

                return(outStream);
            }
            catch (Exception e)
            {
                if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
                {
                    NetworkLog.LogError("Error while wrapping headers");
                }
                if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                {
                    NetworkLog.LogError(e.ToString());
                }

                return(null);
            }
        }
示例#2
0
        private void Update()
        {
            if (!IsOwner)
            {
                return;
            }

            if (agent.destination != lastDestination)
            {
                lastDestination = agent.destination;
                using (PooledBitStream stream = PooledBitStream.Get())
                {
                    using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                    {
                        writer.WriteSinglePacked(agent.destination.x);
                        writer.WriteSinglePacked(agent.destination.y);
                        writer.WriteSinglePacked(agent.destination.z);

                        writer.WriteSinglePacked(agent.velocity.x);
                        writer.WriteSinglePacked(agent.velocity.y);
                        writer.WriteSinglePacked(agent.velocity.z);

                        writer.WriteSinglePacked(transform.position.x);
                        writer.WriteSinglePacked(transform.position.y);
                        writer.WriteSinglePacked(transform.position.z);


                        if (!EnableProximity)
                        {
                            InvokeClientRpcOnEveryonePerformance(OnNavMeshStateUpdate, stream);
                        }
                        else
                        {
                            List <ulong> proximityClients = new List <ulong>();
                            foreach (KeyValuePair <ulong, NetworkedClient> client in NetworkingManager.Singleton.ConnectedClients)
                            {
                                if (client.Value.PlayerObject == null || Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange)
                                {
                                    proximityClients.Add(client.Key);
                                }
                            }
                            InvokeClientRpcPerformance(OnNavMeshStateUpdate, proximityClients, stream);
                        }
                    }
                }
            }

            if (NetworkingManager.Singleton.NetworkTime - lastCorrectionTime >= CorrectionDelay)
            {
                using (PooledBitStream stream = PooledBitStream.Get())
                {
                    using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                    {
                        writer.WriteSinglePacked(agent.velocity.x);
                        writer.WriteSinglePacked(agent.velocity.y);
                        writer.WriteSinglePacked(agent.velocity.z);

                        writer.WriteSinglePacked(transform.position.x);
                        writer.WriteSinglePacked(transform.position.y);
                        writer.WriteSinglePacked(transform.position.z);


                        if (!EnableProximity)
                        {
                            InvokeClientRpcOnEveryonePerformance(OnNavMeshCorrectionUpdate, stream);
                        }
                        else
                        {
                            List <ulong> proximityClients = new List <ulong>();
                            foreach (KeyValuePair <ulong, NetworkedClient> client in NetworkingManager.Singleton.ConnectedClients)
                            {
                                if (client.Value.PlayerObject == null || Vector3.Distance(client.Value.PlayerObject.transform.position, transform.position) <= ProximityRange)
                                {
                                    proximityClients.Add(client.Key);
                                }
                            }
                            InvokeClientRpcPerformance(OnNavMeshCorrectionUpdate, proximityClients, stream);
                        }
                    }
                }
                lastCorrectionTime = NetworkingManager.Singleton.NetworkTime;
            }
        }
示例#3
0
        internal static NetworkedObject CreateSpawnedObject(int networkedPrefabId, uint networkId, uint owner, bool playerObject, uint sceneSpawnedInIndex, bool sceneDelayedSpawn, bool destroyWithScene, Vector3?position, Quaternion?rotation, bool isActive, Stream stream, bool readPayload, int payloadLength, bool readNetworkedVar)
        {
            if (networkedPrefabId >= netManager.NetworkConfig.NetworkedPrefabs.Count || networkedPrefabId < 0)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Cannot spawn the object, invalid prefabIndex: " + networkedPrefabId);
                }
                return(null);
            }

            //Delayed spawning
            if (sceneDelayedSpawn && sceneSpawnedInIndex != NetworkSceneManager.CurrentActiveSceneIndex)
            {
                GameObject prefab       = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].prefab;
                bool       prefabActive = prefab.activeSelf;
                prefab.SetActive(false);
                GameObject go = (position == null && rotation == null) ? MonoBehaviour.Instantiate(prefab) : MonoBehaviour.Instantiate(prefab, position.GetValueOrDefault(Vector3.zero), rotation.GetValueOrDefault(Quaternion.identity));
                prefab.SetActive(prefabActive);

                //Appearantly some wierd behavior when switching scenes can occur that destroys this object even though the scene is
                //not destroyed, therefor we set it to DontDestroyOnLoad here, to prevent that problem.
                MonoBehaviour.DontDestroyOnLoad(go);

                NetworkedObject netObject = go.GetComponent <NetworkedObject>();
                if (netObject == null)
                {
                    if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                    {
                        LogHelper.LogWarning("Please add a NetworkedObject component to the root of all spawnable objects");
                    }
                    netObject = go.AddComponent <NetworkedObject>();
                }

                netObject.NetworkedPrefabName = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].name;
                netObject.IsSpawned           = false;
                netObject.IsPooledObject      = false;

                if (netManager.IsServer)
                {
                    netObject.NetworkId = GetNetworkObjectId();
                }
                else
                {
                    netObject.NetworkId = networkId;
                }

                netObject.destroyWithScene    = destroyWithScene;
                netObject.OwnerClientId       = owner;
                netObject.IsPlayerObject      = playerObject;
                netObject.SceneDelayedSpawn   = sceneDelayedSpawn;
                netObject.sceneSpawnedInIndex = sceneSpawnedInIndex;

                Dictionary <ushort, List <INetworkedVar> > dummyNetworkedVars = new Dictionary <ushort, List <INetworkedVar> >();
                List <NetworkedBehaviour> networkedBehaviours = new List <NetworkedBehaviour>(netObject.GetComponentsInChildren <NetworkedBehaviour>());
                for (ushort i = 0; i < networkedBehaviours.Count; i++)
                {
                    dummyNetworkedVars.Add(i, networkedBehaviours[i].GetDummyNetworkedVars());
                }

                PendingSpawnObject pso = new PendingSpawnObject()
                {
                    netObject           = netObject,
                    dummyNetworkedVars  = dummyNetworkedVars,
                    sceneSpawnedInIndex = sceneSpawnedInIndex,
                    playerObject        = playerObject,
                    owner    = owner,
                    isActive = isActive,
                    payload  = null
                };
                PendingSpawnObjects.Add(netObject.NetworkId, pso);

                pso.SetNetworkedVarData(stream);
                if (readPayload)
                {
                    MLAPI.Serialization.BitStream payloadStream = new MLAPI.Serialization.BitStream();
                    payloadStream.CopyUnreadFrom(stream, payloadLength);
                    stream.Position += payloadLength;
                    pso.payload      = payloadStream;
                }

                return(netObject);
            }

            //Normal spawning
            {
                GameObject prefab = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].prefab;
                GameObject go     = (position == null && rotation == null) ? MonoBehaviour.Instantiate(prefab) : MonoBehaviour.Instantiate(prefab, position.GetValueOrDefault(Vector3.zero), rotation.GetValueOrDefault(Quaternion.identity));

                NetworkedObject netObject = go.GetComponent <NetworkedObject>();
                if (netObject == null)
                {
                    if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                    {
                        LogHelper.LogWarning("Please add a NetworkedObject component to the root of all spawnable objects");
                    }
                    netObject = go.AddComponent <NetworkedObject>();
                }

                if (readNetworkedVar)
                {
                    netObject.SetNetworkedVarData(stream);
                }

                netObject.NetworkedPrefabName = netManager.NetworkConfig.NetworkedPrefabs[networkedPrefabId].name;
                netObject.IsSpawned           = true;
                netObject.IsPooledObject      = false;

                if (netManager.IsServer)
                {
                    netObject.NetworkId = GetNetworkObjectId();
                }
                else
                {
                    netObject.NetworkId = networkId;
                }

                netObject.destroyWithScene    = destroyWithScene;
                netObject.OwnerClientId       = owner;
                netObject.IsPlayerObject      = playerObject;
                netObject.SceneDelayedSpawn   = sceneDelayedSpawn;
                netObject.sceneSpawnedInIndex = sceneSpawnedInIndex;

                SpawnedObjects.Add(netObject.NetworkId, netObject);
                SpawnedObjectsList.Add(netObject);
                if (playerObject)
                {
                    NetworkingManager.Singleton.ConnectedClients[owner].PlayerObject = netObject;
                }

                if (readPayload)
                {
                    using (PooledBitStream payloadStream = PooledBitStream.Get())
                    {
                        payloadStream.CopyUnreadFrom(stream, payloadLength);
                        stream.Position += payloadLength;
                        netObject.InvokeBehaviourNetworkSpawn(payloadStream);
                    }
                }
                else
                {
                    netObject.InvokeBehaviourNetworkSpawn(null);
                }

                netObject.gameObject.SetActive(isActive);
                return(netObject);
            }
        }
示例#4
0
        // This method is responsible for unwrapping a message, that is extracting the messagebody.
        // Could include decrypting and/or authentication.
        internal static BitStream UnwrapMessage(BitStream inputStream, ulong clientId, out byte messageType, out SecuritySendFlags security)
        {
            using (PooledBitReader inputHeaderReader = PooledBitReader.Get(inputStream))
            {
                try
                {
                    if (inputStream.Length < 1)
                    {
                        if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
                        {
                            NetworkLog.LogError("The incoming message was too small");
                        }
                        messageType = MLAPIConstants.INVALID;
                        security    = SecuritySendFlags.None;
                        return(null);
                    }

                    bool isEncrypted     = inputHeaderReader.ReadBit();
                    bool isAuthenticated = inputHeaderReader.ReadBit();

                    if (isEncrypted && isAuthenticated)
                    {
                        security = SecuritySendFlags.Encrypted | SecuritySendFlags.Authenticated;
                    }
                    else if (isEncrypted)
                    {
                        security = SecuritySendFlags.Encrypted;
                    }
                    else if (isAuthenticated)
                    {
                        security = SecuritySendFlags.Authenticated;
                    }
                    else
                    {
                        security = SecuritySendFlags.None;
                    }


#if !DISABLE_CRYPTOGRAPHY
                    if (isEncrypted || isAuthenticated)
                    {
                        if (!NetworkingManager.Singleton.NetworkConfig.EnableEncryption)
                        {
                            if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                            {
                                NetworkLog.LogError("Got a encrypted and/or authenticated message but key exchange (\"encryption\") was not enabled");
                            }
                            messageType = MLAPIConstants.INVALID;
                            return(null);
                        }

                        // Skip last bits in first byte
                        inputHeaderReader.SkipPadBits();

                        if (isAuthenticated)
                        {
                            long hmacStartPos = inputStream.Position;

                            int readHmacLength = inputStream.Read(HMAC_BUFFER, 0, HMAC_BUFFER.Length);

                            if (readHmacLength != HMAC_BUFFER.Length)
                            {
                                if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                                {
                                    NetworkLog.LogError("HMAC length was invalid");
                                }
                                messageType = MLAPIConstants.INVALID;
                                return(null);
                            }

                            // Now we have read the HMAC, we need to set the hmac in the input to 0s to perform the HMAC.
                            inputStream.Position = hmacStartPos;
                            inputStream.Write(HMAC_PLACEHOLDER, 0, HMAC_PLACEHOLDER.Length);

                            byte[] key = NetworkingManager.Singleton.IsServer ? CryptographyHelper.GetClientKey(clientId) : CryptographyHelper.GetServerKey();

                            if (key == null)
                            {
                                if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                                {
                                    NetworkLog.LogError("Failed to grab key");
                                }
                                messageType = MLAPIConstants.INVALID;
                                return(null);
                            }

                            using (HMACSHA256 hmac = new HMACSHA256(key))
                            {
                                byte[] computedHmac = hmac.ComputeHash(inputStream.GetBuffer(), 0, (int)inputStream.Length);


                                if (!CryptographyHelper.ConstTimeArrayEqual(computedHmac, HMAC_BUFFER))
                                {
                                    if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                                    {
                                        NetworkLog.LogError("Received HMAC did not match the computed HMAC");
                                    }
                                    messageType = MLAPIConstants.INVALID;
                                    return(null);
                                }
                            }
                        }

                        if (isEncrypted)
                        {
                            int ivRead = inputStream.Read(IV_BUFFER, 0, IV_BUFFER.Length);

                            if (ivRead != IV_BUFFER.Length)
                            {
                                if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
                                {
                                    NetworkLog.LogError("Invalid IV size");
                                }
                                messageType = MLAPIConstants.INVALID;
                                return(null);
                            }

                            PooledBitStream outputStream = PooledBitStream.Get();

                            using (RijndaelManaged rijndael = new RijndaelManaged())
                            {
                                rijndael.IV      = IV_BUFFER;
                                rijndael.Padding = PaddingMode.PKCS7;

                                byte[] key = NetworkingManager.Singleton.IsServer ? CryptographyHelper.GetClientKey(clientId) : CryptographyHelper.GetServerKey();

                                if (key == null)
                                {
                                    if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                                    {
                                        NetworkLog.LogError("Failed to grab key");
                                    }
                                    messageType = MLAPIConstants.INVALID;
                                    return(null);
                                }

                                rijndael.Key = key;

                                using (CryptoStream cryptoStream = new CryptoStream(outputStream, rijndael.CreateDecryptor(), CryptoStreamMode.Write))
                                {
                                    cryptoStream.Write(inputStream.GetBuffer(), (int)inputStream.Position, (int)(inputStream.Length - inputStream.Position));
                                }

                                outputStream.Position = 0;

                                if (outputStream.Length == 0)
                                {
                                    if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
                                    {
                                        NetworkLog.LogError("The incoming message was too small");
                                    }
                                    messageType = MLAPIConstants.INVALID;
                                    return(null);
                                }

                                int msgType = outputStream.ReadByte();
                                messageType = msgType == -1 ? MLAPIConstants.INVALID : (byte)msgType;
                            }

                            return(outputStream);
                        }
                        else
                        {
                            if (inputStream.Length - inputStream.Position <= 0)
                            {
                                if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
                                {
                                    NetworkLog.LogError("The incoming message was too small");
                                }
                                messageType = MLAPIConstants.INVALID;
                                return(null);
                            }

                            int msgType = inputStream.ReadByte();
                            messageType = msgType == -1 ? MLAPIConstants.INVALID : (byte)msgType;
                            return(inputStream);
                        }
                    }
                    else
                    {
#endif
                    messageType = inputHeaderReader.ReadByteBits(6);
                    // The input stream is now ready to be read from. It's "safe" and has the correct position
                    return(inputStream);

#if !DISABLE_CRYPTOGRAPHY
                }
#endif
                }
                catch (Exception e)
                {
                    if (NetworkLog.CurrentLogLevel <= LogLevel.Normal)
                    {
                        NetworkLog.LogError("Error while unwrapping headers");
                    }
                    if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                    {
                        NetworkLog.LogError(e.ToString());
                    }

                    security    = SecuritySendFlags.None;
                    messageType = MLAPIConstants.INVALID;
                    return(null);
                }
            }
        }
示例#5
0
        private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStream)
        {
            if (NetworkingManager.Singleton.NetworkConfig.UsePrefabSync)
            {
                SpawnManager.DestroySceneObjects();

                using (PooledBitReader reader = PooledBitReader.Get(objectStream))
                {
                    uint newObjectsCount = reader.ReadUInt32Packed();

                    for (int i = 0; i < newObjectsCount; i++)
                    {
                        bool  isPlayerObject = reader.ReadBool();
                        ulong networkId      = reader.ReadUInt64Packed();
                        ulong owner          = reader.ReadUInt64Packed();

                        ulong prefabHash = reader.ReadUInt64Packed();

                        bool destroyWithScene = reader.ReadBool();

                        Vector3    position = new Vector3(reader.ReadSinglePacked(), reader.ReadSinglePacked(), reader.ReadSinglePacked());
                        Quaternion rotation = Quaternion.Euler(reader.ReadSinglePacked(), reader.ReadSinglePacked(), reader.ReadSinglePacked());

                        NetworkedObject networkedObject = SpawnManager.CreateLocalNetworkedObject(false, 0, prefabHash, position, rotation);
                        SpawnManager.SpawnNetworkedObjectLocally(networkedObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, destroyWithScene);
                    }
                }
            }
            else
            {
                NetworkedObject[] networkedObjects = MonoBehaviour.FindObjectsOfType <NetworkedObject>();

                SpawnManager.ClientCollectSoftSyncSceneObjectSweep(networkedObjects);

                using (PooledBitReader reader = PooledBitReader.Get(objectStream))
                {
                    uint newObjectsCount = reader.ReadUInt32Packed();

                    for (int i = 0; i < newObjectsCount; i++)
                    {
                        bool  isPlayerObject = reader.ReadBool();
                        ulong networkId      = reader.ReadUInt64Packed();
                        ulong owner          = reader.ReadUInt64Packed();

                        ulong instanceId = reader.ReadUInt64Packed();

                        bool destroyWithScene = reader.ReadBool();

                        NetworkedObject networkedObject = SpawnManager.CreateLocalNetworkedObject(true, instanceId, 0, null, null);
                        SpawnManager.SpawnNetworkedObjectLocally(networkedObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, destroyWithScene);
                    }
                }
            }

            using (PooledBitStream stream = PooledBitStream.Get())
            {
                using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                {
                    writer.WriteByteArray(switchSceneGuid.ToByteArray());
                    InternalMessageHandler.Send(NetworkingManager.Singleton.ServerClientId, MLAPIConstants.MLAPI_CLIENT_SWITCH_SCENE_COMPLETED, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null);
                }
            }

            isSwitching = false;

            if (OnSceneSwitched != null)
            {
                OnSceneSwitched();
            }
        }
示例#6
0
    // Essentially, when this is passed an empty list, the okay will be sent to the server
    IEnumerator SendNeededFilesListToSender(List <int> _fileIDs)
    {
        bool allFilesReceived = _fileIDs.Count == 0;

        Debug.Log("sending needed files, files: " + _fileIDs.Count);

        PooledBitStream bitStream = PooledBitStream.Get();
        PooledBitWriter writer    = PooledBitWriter.Get(bitStream);

        if (allFilesReceived)
        {
            writer.WriteBit(true);
            writer.WriteIntArray(_fileIDs.ToArray());
            writer.WriteBit(true);

            CustomMessagingManager.SendNamedMessage(MessageName, SenderID, bitStream, "MLAPI_INTERNAL");

            bitStream.Dispose();
            writer.Dispose();
            _fileIDs.Clear();

            StopListening();

            if (OnDownloadComplete != null)
            {
                OnDownloadComplete(SendOrReceiveFlag.Receive, SenderID);
            }

            ChangeState(LargeRPCState.Idle);
        }
        else
        {
            var        i   = 0;
            List <int> ids = _fileIDs;
            foreach (var id in ids)
            {
                i++;

                bool isFinalPacket = i >= _fileIDs.Count;

                if (i >= _fileIDs.Count)
                {
                    writer.WriteBit(isFinalPacket);
                    writer.WriteIntArray(_fileIDs.ToArray());
                    writer.WriteBit(false);

                    CustomMessagingManager.SendNamedMessage(MessageName, SenderID, bitStream, "MLAPI_INTERNAL");

                    bitStream.Dispose();
                    writer.Dispose();

                    bitStream = PooledBitStream.Get();
                    writer    = PooledBitWriter.Get(bitStream);

                    _fileIDs.Clear();

                    yield return(new WaitForSeconds(1 / 8));

                    break;
                }
            }
        }

        yield break;
    }
示例#7
0
        private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStream)
        {
            if (!NetworkingManager.Singleton.NetworkConfig.EnableSceneManagement || NetworkingManager.Singleton.NetworkConfig.UsePrefabSync)
            {
                SpawnManager.DestroySceneObjects();

                using (PooledBitReader reader = PooledBitReader.Get(objectStream))
                {
                    uint newObjectsCount = reader.ReadUInt32Packed();

                    for (int i = 0; i < newObjectsCount; i++)
                    {
                        bool  isPlayerObject  = reader.ReadBool();
                        ulong networkId       = reader.ReadUInt64Packed();
                        ulong owner           = reader.ReadUInt64Packed();
                        bool  hasParent       = reader.ReadBool();
                        ulong?parentNetworkId = null;

                        if (hasParent)
                        {
                            parentNetworkId = reader.ReadUInt64Packed();
                        }

                        ulong prefabHash = reader.ReadUInt64Packed();

                        Vector3?   position = null;
                        Quaternion?rotation = null;
                        if (reader.ReadBool())
                        {
                            position = new Vector3(reader.ReadSinglePacked(), reader.ReadSinglePacked(), reader.ReadSinglePacked());
                            rotation = Quaternion.Euler(reader.ReadSinglePacked(), reader.ReadSinglePacked(), reader.ReadSinglePacked());
                        }

                        NetworkedObject networkedObject = SpawnManager.CreateLocalNetworkedObject(false, 0, prefabHash, parentNetworkId, position, rotation);
                        SpawnManager.SpawnNetworkedObjectLocally(networkedObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, false);

                        Queue <BufferManager.BufferedMessage> bufferQueue = BufferManager.ConsumeBuffersForNetworkId(networkId);

                        // Apply buffered messages
                        if (bufferQueue != null)
                        {
                            while (bufferQueue.Count > 0)
                            {
                                BufferManager.BufferedMessage message = bufferQueue.Dequeue();

                                NetworkingManager.Singleton.HandleIncomingData(message.sender, message.channelName, new ArraySegment <byte>(message.payload.GetBuffer(), (int)message.payload.Position, (int)message.payload.Length), message.receiveTime, false);

                                BufferManager.RecycleConsumedBufferedMessage(message);
                            }
                        }
                    }
                }
            }
            else
            {
                NetworkedObject[] networkedObjects = MonoBehaviour.FindObjectsOfType <NetworkedObject>();

                SpawnManager.ClientCollectSoftSyncSceneObjectSweep(networkedObjects);

                using (PooledBitReader reader = PooledBitReader.Get(objectStream))
                {
                    uint newObjectsCount = reader.ReadUInt32Packed();

                    for (int i = 0; i < newObjectsCount; i++)
                    {
                        bool  isPlayerObject  = reader.ReadBool();
                        ulong networkId       = reader.ReadUInt64Packed();
                        ulong owner           = reader.ReadUInt64Packed();
                        bool  hasParent       = reader.ReadBool();
                        ulong?parentNetworkId = null;

                        if (hasParent)
                        {
                            parentNetworkId = reader.ReadUInt64Packed();
                        }

                        ulong instanceId = reader.ReadUInt64Packed();

                        NetworkedObject networkedObject = SpawnManager.CreateLocalNetworkedObject(true, instanceId, 0, parentNetworkId, null, null);
                        SpawnManager.SpawnNetworkedObjectLocally(networkedObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, false);

                        Queue <BufferManager.BufferedMessage> bufferQueue = BufferManager.ConsumeBuffersForNetworkId(networkId);

                        // Apply buffered messages
                        if (bufferQueue != null)
                        {
                            while (bufferQueue.Count > 0)
                            {
                                BufferManager.BufferedMessage message = bufferQueue.Dequeue();

                                NetworkingManager.Singleton.HandleIncomingData(message.sender, message.channelName, new ArraySegment <byte>(message.payload.GetBuffer(), (int)message.payload.Position, (int)message.payload.Length), message.receiveTime, false);

                                BufferManager.RecycleConsumedBufferedMessage(message);
                            }
                        }
                    }
                }
            }

            using (PooledBitStream stream = PooledBitStream.Get())
            {
                using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                {
                    writer.WriteByteArray(switchSceneGuid.ToByteArray());
                    NetworkedObject networkedObject = null;
                    InternalMessageSender.Send(NetworkingManager.Singleton.ServerClientId, MLAPIConstants.MLAPI_CLIENT_SWITCH_SCENE_COMPLETED, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, networkedObject);
                }
            }

            isSwitching = false;

            if (OnSceneSwitched != null)
            {
                OnSceneSwitched();
            }
        }
    internal void Tick(uint tick)
    {
        if (IsServer)
        {
            using (PooledBitStream stream = PooledBitStream.Get())
            {
                using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                {
                    writer.WriteUInt32(tick);
                    Dictionary <ulong, IEntityState> states = new Dictionary <ulong, IEntityState>(entities.Count);

                    foreach (Entity entity in entities.Values)
                    {
                        IEntityState state = entity.DoStateTick(tick);
                        if (state != null)
                        {
                            states.Add(entity.NetworkId, state);
                        }
                    }

                    writer.WriteInt32(states.Count);

                    foreach (var state in states)
                    {
                        writer.WriteUInt64(state.Key);
                        state.Value.Serialize(writer);
                    }

                    CustomMessagingManager.SendNamedMessage("NetworkState", null, stream);
                }
            }
        }

        else
        {
            foreach (Entity entity in entities.Values)
            {
                entity.DoStateTick(tick);
            }

            uint predictTicks = (uint)Math.Ceiling(RTT / FixedStep) + 2 * Deviation;

            for (uint i = 0; i < predictTicks; i++)
            {
                if (tick + i > LastPredictedTick)
                {
                    using (PooledBitStream stream = PooledBitStream.Get())
                    {
                        using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                        {
                            LastPredictedTick = tick + i;
                            var authEntities = entities.Values.Where(e => e.IsOwner);
                            int count        = authEntities.Count();
                            Dictionary <ulong, IEntityInput> inputs = new Dictionary <ulong, IEntityInput>(count);

                            foreach (Entity entity in authEntities)
                            {
                                IEntityInput input = entity.DoInputTick(tick + i);
                                if (input != null)
                                {
                                    inputs.Add(entity.NetworkId, input);
                                }
                            }

                            writer.WriteUInt32(tick + i);
                            writer.WriteInt32(inputs.Count);

                            foreach (var input in inputs)
                            {
                                writer.WriteUInt64(input.Key);
                                input.Value.Serialize(writer);
                            }

                            CustomMessagingManager.SendNamedMessage("NetworkInput", NetworkingManager.Singleton.ServerClientId, stream);
                        }
                    }
                }

                foreach (Entity entity in entities.Values.Where(e => e.extrapolate || e.IsOwner))
                {
                    entity.DoStateTick(tick + i);
                }
            }

            foreach (Entity entity in entities.Values)
            {
                entity.Present();
            }
        }
    }
示例#9
0
        internal static void SpawnObject(NetworkedObject netObject, uint?clientOwnerId = null, Stream payload = null)
        {
            if (netObject.isSpawned)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Object already spawned");
                }
                return;
            }
            else if (!netManager.isServer)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Only server can spawn objects");
                }
                return;
            }
            else if (!netManager.NetworkConfig.NetworkPrefabIds.ContainsKey(netObject.NetworkedPrefabName))
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("The prefab name " + netObject.NetworkedPrefabName + " does not exist as a networkedPrefab");
                }
                return;
            }
            else if (!netManager.NetworkConfig.HandleObjectSpawning)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("NetworkConfig is set to not handle object spawning");
                }
                return;
            }
            uint netId = GetNetworkObjectId();

            netObject.NetworkId = netId;
            SpawnedObjects.Add(netId, netObject);
            SpawnedObjectsList.Add(netObject);
            netObject.isSpawned   = true;
            netObject.sceneObject = false;

            if (clientOwnerId != null)
            {
                netObject.OwnerClientId = clientOwnerId.Value;
                NetworkingManager.singleton.ConnectedClients[clientOwnerId.Value].OwnedObjects.Add(netObject);
            }

            if (payload == null)
            {
                netObject.InvokeBehaviourNetworkSpawn(null);
            }
            else
            {
                netObject.InvokeBehaviourNetworkSpawn(payload);
            }

            foreach (var client in netManager.ConnectedClients)
            {
                using (PooledBitStream stream = PooledBitStream.Get())
                {
                    using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                    {
                        writer.WriteBool(false);
                        writer.WriteUInt32Packed(netObject.NetworkId);
                        writer.WriteUInt32Packed(netObject.OwnerClientId);
                        writer.WriteInt32Packed(netManager.NetworkConfig.NetworkPrefabIds[netObject.NetworkedPrefabName]);
                        writer.WriteBool(netObject.sceneObject == null ? true : netObject.sceneObject.Value);

                        writer.WriteSinglePacked(netObject.transform.position.x);
                        writer.WriteSinglePacked(netObject.transform.position.y);
                        writer.WriteSinglePacked(netObject.transform.position.z);

                        writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x);
                        writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y);
                        writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z);

                        writer.WriteBool(payload != null);

                        netObject.WriteNetworkedVarData(stream, client.Key);

                        if (payload != null)
                        {
                            stream.CopyFrom(payload);
                        }

                        InternalMessageHandler.Send(client.Key, MLAPIConstants.MLAPI_ADD_OBJECT, "MLAPI_INTERNAL", stream);
                    }
                }
            }
        }
示例#10
0
        public void HandleSpawnMessage(ulong clientID, Stream stream, float receiveTime)
        {
            using (PooledBitReader reader = PooledBitReader.Get(stream))
            {
                ulong networkID     = reader.ReadUInt64Packed(); //Network ID
                ulong ownerID       = reader.ReadUInt64Packed(); //Owner
                Type  behaviourType = RPCTypeDefinition.GetTypeFromHash(reader.ReadUInt64Packed());
                bool  hasUniqueHash = reader.ReadBool();
                ulong uniqueHash    = 0;
                if (hasUniqueHash)
                {
                    uniqueHash = reader.ReadUInt64Packed();
                }
                bool ownerCanUnspawn  = reader.ReadBool();
                bool destroyOnUnspawn = reader.ReadBool();

                //Read spawn payload
                PooledBitStream payloadStream = null;
                if (reader.ReadBool())
                {
                    payloadStream = PooledBitStream.Get();
                    int payloadLength = reader.ReadInt32Packed();
                    payloadStream.CopyUnreadFrom(stream, payloadLength);
                    stream.Position       += payloadLength;
                    payloadStream.Position = 0;
                }

                if (networkManager.enableLogging)
                {
                    string s = "Received add object event from server. Object: " + behaviourType.ToString() + " | Network ID: " + networkID + " | Owner: " + ownerID + " | Has Unique Hash: " + hasUniqueHash + " | ";
                    if (hasUniqueHash)
                    {
                        s += uniqueHash + " | ";
                    }
                    s += "Owner Can Unspawn: " + ownerCanUnspawn + " | Destroy On Unspawn: " + destroyOnUnspawn;
                    Debug.Log(s);
                }

                if (hasUniqueHash)
                {
                    if (m_LocalPendingBehaviours.TryGetValue(uniqueHash, out PendingNetworkBehaviour pendingBehaviour))
                    {
                        if (pendingBehaviour.reference.networkBehaviour.GetType() != behaviourType)
                        {
                            Debug.LogError("Received add object message where the remote network behaviour type(" + behaviourType.ToString() + ") does not match up with local network behaviour type (" + pendingBehaviour.reference.networkBehaviour.GetType() + ") with same unique ID(" + pendingBehaviour.reference.networkBehaviour.uniqueID + ").", pendingBehaviour.reference.networkBehaviour);
                            return;
                        }

                        //Clean up pending
                        m_LocalPendingBehaviours.Remove(uniqueHash);
                        m_LocalPendingBehavioursList.Remove(pendingBehaviour.reference.networkBehaviour);

                        OnObjectConnectSuccess(pendingBehaviour.reference, networkID, ownerID, ownerCanUnspawn, destroyOnUnspawn, payloadStream);
                        if (payloadStream != null)
                        {
                            payloadStream.Dispose();
                        }
                    }
                    else if (m_RemotePendingBehavioursHashes.ContainsKey(uniqueHash))
                    {
                        Debug.LogError("Received duplicate 'add object' message for hash '" + uniqueHash + "'.");
                        return;
                    }
                    else if (m_RemotePendingBehaviours.ContainsKey(networkID))
                    {
                        Debug.LogError("Recevied duplicate 'add object' message for network ID '" + networkID + "'.");
                        return;
                    }
                    else
                    {
                        PendingNetworkBehaviour pendingBehaviourReference = new PendingNetworkBehaviour()
                        {
                            isRemoteBehaviour = true, uniqueHash = uniqueHash, ownerID = ownerID, networkID = networkID, ownerCanUnspawn = ownerCanUnspawn, destroyOnUnspawn = destroyOnUnspawn, spawnPayload = payloadStream
                        };
                        m_RemotePendingBehavioursHashes.Add(uniqueHash, pendingBehaviourReference);
                        m_RemotePendingBehaviours.Add(networkID, pendingBehaviourReference);
                    }
                }
                else //No unique hash
                {
                    //Build network behaviour
                    GameObject behaviourObject = new GameObject("Server Network Object");

                    //All this stuff just in case the instantiate behaviour also instantiates other network behaviours in its awake function
                    m_TrackAwakeSpawns = true;

                    NetworkBehaviour serverBehaviour = (NetworkBehaviour)behaviourObject.AddComponent(behaviourType);

                    m_TrackAwakeSpawns = false;
                    if (m_BehavioursAwaitingSpawn.Count > 0)
                    {
                        while (m_BehavioursAwaitingSpawn.Count > 0)
                        {
                            NetworkBehaviourReference reference = m_BehavioursAwaitingSpawn.Dequeue();
                            if (reference.networkBehaviour == serverBehaviour)
                            {
                                OnObjectConnectSuccess(reference, networkID, ownerID, ownerCanUnspawn, destroyOnUnspawn, payloadStream);
                                if (payloadStream != null)
                                {
                                    payloadStream.Dispose();
                                }
                            }
                            else
                            {
                                SpawnOnNetworkClient(reference.networkBehaviour, reference.connectedClientCallback, reference.disconnectedDelegate, reference.localRPCDelegate, reference.ownerChangeDelegate);
                            }
                        }
                    }
                    if (!serverBehaviour.isNetworkSpawned)
                    {
                        serverBehaviour.uniqueID = "NETWORK_SERVER_BEHAVIOUR_" + networkID.ToString();
                        serverBehaviour.SpawnOnNetwork();
                        ulong hash = serverBehaviour.uniqueID.GetStableHash(networkManager.config.rpcHashSize);

                        PendingNetworkBehaviour pendingBehaviour = m_LocalPendingBehaviours[hash];
                        //Clean up pending
                        m_LocalPendingBehaviours.Remove(uniqueHash);
                        m_LocalPendingBehavioursList.Remove(serverBehaviour);

                        OnObjectConnectSuccess(pendingBehaviour.reference, networkID, ownerID, ownerCanUnspawn, destroyOnUnspawn, payloadStream);
                        if (payloadStream != null)
                        {
                            payloadStream.Dispose();
                        }
                    }
                }
            }
        }
示例#11
0
        internal void NetworkedVarUpdate()
        {
            if (!networkedVarInit)
            {
                NetworkedVarInit();
            }

            //TODO: Do this efficiently.

            if (!CouldHaveDirtyVars())
            {
                return;
            }

            networkedVarIndexesToReset.Clear();
            networkedVarIndexesToResetSet.Clear();

            for (int i = 0; i < NetworkingManager.singleton.ConnectedClientsList.Count; i++)
            {
                //This iterates over every "channel group".
                for (int j = 0; j < channelMappedVarIndexes.Count; j++)
                {
                    using (PooledBitStream stream = PooledBitStream.Get())
                    {
                        using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                        {
                            writer.WriteUInt32Packed(networkId);
                            writer.WriteUInt16Packed(networkedObject.GetOrderIndex(this));

                            uint clientId   = NetworkingManager.singleton.ConnectedClientsList[i].ClientId;
                            bool writtenAny = false;
                            for (int k = 0; k < networkedVarFields.Count; k++)
                            {
                                if (!channelMappedVarIndexes[j].Contains(k))
                                {
                                    //This var does not belong to the currently iterating channel group.
                                    writer.WriteBool(false);
                                    continue;
                                }

                                bool isDirty = networkedVarFields[k].IsDirty(); //cache this here. You never know what operations users will do in the dirty methods
                                writer.WriteBool(isDirty);

                                if (isDirty && (!isServer || networkedVarFields[k].CanClientRead(clientId)))
                                {
                                    writtenAny = true;
                                    networkedVarFields[k].WriteDelta(stream);
                                    if (!networkedVarIndexesToResetSet.Contains(k))
                                    {
                                        networkedVarIndexesToResetSet.Add(k);
                                        networkedVarIndexesToReset.Add(k);
                                    }
                                }
                            }

                            if (writtenAny)
                            {
                                if (isServer)
                                {
                                    InternalMessageHandler.Send(clientId, MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA, channelsForVarGroups[j], stream, SecuritySendFlags.None);
                                }
                                else
                                {
                                    InternalMessageHandler.Send(NetworkingManager.singleton.ServerClientId, MLAPIConstants.MLAPI_NETWORKED_VAR_DELTA, channelsForVarGroups[j], stream, SecuritySendFlags.None);
                                }
                            }
                        }
                    }
                }
            }

            for (int i = 0; i < networkedVarIndexesToReset.Count; i++)
            {
                networkedVarFields[networkedVarIndexesToReset[i]].ResetDirty();
            }
        }
示例#12
0
        internal static void OnDestroyObject(uint networkId, bool destroyGameObject)
        {
            if ((netManager == null || !netManager.NetworkConfig.HandleObjectSpawning))
            {
                return;
            }

            //Removal of pending object
            //Even though pending objects is marked with DontDestroyOnLoad, the OnDestroy method is invoked on pending objects. They are however not
            //destroyed (probably a unity bug for having an gameobject spawned as inactive). Therefore we only actual remove it from the list if
            //destroyGameObject is set to true, meaning MLAPI decided to destroy it, not unity.
            if (destroyGameObject == true && PendingSpawnObjects.ContainsKey(networkId))
            {
                if (!PendingSpawnObjects[networkId].netObject.IsOwnedByServer && !PendingSpawnObjects[networkId].netObject.IsPlayerObject &&
                    netManager.ConnectedClients.ContainsKey(PendingSpawnObjects[networkId].netObject.OwnerClientId))
                {
                    //Someone owns it.
                    for (int i = NetworkingManager.Singleton.ConnectedClients[PendingSpawnObjects[networkId].netObject.OwnerClientId].OwnedObjects.Count - 1; i > -1; i--)
                    {
                        if (NetworkingManager.Singleton.ConnectedClients[PendingSpawnObjects[networkId].netObject.OwnerClientId].OwnedObjects[i].NetworkId == networkId)
                        {
                            NetworkingManager.Singleton.ConnectedClients[PendingSpawnObjects[networkId].netObject.OwnerClientId].OwnedObjects.RemoveAt(i);
                        }
                    }
                }

                GameObject pendingGameObject = PendingSpawnObjects[networkId].netObject.gameObject;
                if (pendingGameObject != null)
                {
                    MonoBehaviour.Destroy(pendingGameObject);
                }
                PendingSpawnObjects.Remove(networkId);
            }

            //Removal of spawned object
            if (!SpawnedObjects.ContainsKey(networkId))
            {
                return;
            }
            if (!SpawnedObjects[networkId].IsOwnedByServer && !SpawnedObjects[networkId].IsPlayerObject &&
                netManager.ConnectedClients.ContainsKey(SpawnedObjects[networkId].OwnerClientId))
            {
                //Someone owns it.
                for (int i = NetworkingManager.Singleton.ConnectedClients[SpawnedObjects[networkId].OwnerClientId].OwnedObjects.Count - 1; i > -1; i--)
                {
                    if (NetworkingManager.Singleton.ConnectedClients[SpawnedObjects[networkId].OwnerClientId].OwnedObjects[i].NetworkId == networkId)
                    {
                        NetworkingManager.Singleton.ConnectedClients[SpawnedObjects[networkId].OwnerClientId].OwnedObjects.RemoveAt(i);
                    }
                }
            }
            SpawnedObjects[networkId].IsSpawned = false;

            if (netManager != null && netManager.IsServer)
            {
                releasedNetworkObjectIds.Push(networkId);
                if (SpawnedObjects[networkId] != null)
                {
                    using (PooledBitStream stream = PooledBitStream.Get())
                    {
                        using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                        {
                            writer.WriteUInt32Packed(networkId);

                            InternalMessageHandler.Send(MLAPIConstants.MLAPI_DESTROY_OBJECT, "MLAPI_INTERNAL", stream, SecuritySendFlags.None);
                        }
                    }
                }
            }

            GameObject go = SpawnedObjects[networkId].gameObject;

            if (destroyGameObject && go != null)
            {
                MonoBehaviour.Destroy(go);
            }
            SpawnedObjects.Remove(networkId);
            for (int i = SpawnedObjectsList.Count - 1; i > -1; i--)
            {
                if (SpawnedObjectsList[i].NetworkId == networkId)
                {
                    SpawnedObjectsList.RemoveAt(i);
                }
            }
        }
示例#13
0
        internal static void SpawnObject(NetworkedObject netObject, uint?clientOwnerId = null, Stream payload = null, bool destroyWithScene = false)
        {
            if (netObject.IsSpawned)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Object already spawned");
                }
                return;
            }
            else if (!netManager.IsServer)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Only server can spawn objects");
                }
                return;
            }
            else if (SpawnManager.GetNetworkedPrefabIndexOfName(netObject.NetworkedPrefabName) == -1)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("The prefab name " + netObject.NetworkedPrefabName + " does not exist as a networkedPrefab");
                }
                return;
            }
            else if (!netManager.NetworkConfig.HandleObjectSpawning)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("NetworkConfig is set to not handle object spawning");
                }
                return;
            }
            uint netId = GetNetworkObjectId();

            netObject.NetworkId = netId;
            SpawnedObjects.Add(netId, netObject);
            SpawnedObjectsList.Add(netObject);
            netObject.IsSpawned           = true;
            netObject.destroyWithScene    = destroyWithScene;
            netObject.sceneSpawnedInIndex = NetworkSceneManager.CurrentActiveSceneIndex;

            if (clientOwnerId != null)
            {
                netObject.OwnerClientId = clientOwnerId.Value;
                NetworkingManager.Singleton.ConnectedClients[clientOwnerId.Value].OwnedObjects.Add(netObject);
            }

            if (payload == null)
            {
                netObject.InvokeBehaviourNetworkSpawn(null);
            }
            else
            {
                netObject.InvokeBehaviourNetworkSpawn(payload);
            }

            foreach (var client in netManager.ConnectedClients)
            {
                using (PooledBitStream stream = PooledBitStream.Get())
                {
                    using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                    {
                        writer.WriteBool(false);
                        writer.WriteUInt32Packed(netObject.NetworkId);
                        writer.WriteUInt32Packed(netObject.OwnerClientId);
                        writer.WriteUInt64Packed(netObject.NetworkedPrefabHash);

                        writer.WriteBool(netObject.destroyWithScene == null ? true : netObject.destroyWithScene.Value);
                        writer.WriteBool(netObject.SceneDelayedSpawn);
                        writer.WriteUInt32Packed(netObject.sceneSpawnedInIndex);

                        writer.WriteSinglePacked(netObject.transform.position.x);
                        writer.WriteSinglePacked(netObject.transform.position.y);
                        writer.WriteSinglePacked(netObject.transform.position.z);

                        writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.x);
                        writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.y);
                        writer.WriteSinglePacked(netObject.transform.rotation.eulerAngles.z);

                        writer.WriteBool(payload != null);
                        if (payload != null)
                        {
                            writer.WriteInt32Packed((int)payload.Length);
                        }

                        netObject.WriteNetworkedVarData(stream, client.Key);

                        if (payload != null)
                        {
                            stream.CopyFrom(payload);
                        }

                        InternalMessageHandler.Send(client.Key, MLAPIConstants.MLAPI_ADD_OBJECT, "MLAPI_INTERNAL", stream, SecuritySendFlags.None);
                    }
                }
            }
        }
示例#14
0
        // Ran on both server and client
        internal static void SpawnNetworkedObjectLocally(NetworkedObject netObject, ulong networkId, bool sceneObject, bool playerObject, ulong?ownerClientId, Stream dataStream, bool readPayload, int payloadLength, bool readNetworkedVar, bool destroyWithScene)
        {
            if (netObject == null)
            {
                throw new ArgumentNullException(nameof(netObject), "Cannot spawn null object");
            }

            if (netObject.IsSpawned)
            {
                throw new SpawnStateException("Object is already spawned");
            }

            if (readNetworkedVar && NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar)
            {
                netObject.SetNetworkedVarData(dataStream);
                netObject.SetSyncedVarData(dataStream);
            }

            netObject.IsSpawned = true;

            netObject.IsSceneObject = sceneObject;
            netObject.NetworkId     = networkId;

            netObject.DestroyWithScene = sceneObject || destroyWithScene;

            netObject._ownerClientId = ownerClientId;
            netObject.IsPlayerObject = playerObject;

            SpawnedObjects.Add(netObject.NetworkId, netObject);
            SpawnedObjectsList.Add(netObject);

            if (ownerClientId != null)
            {
                if (NetworkingManager.Singleton.IsServer)
                {
                    if (playerObject)
                    {
                        NetworkingManager.Singleton.ConnectedClients[ownerClientId.Value].PlayerObject = netObject;
                    }
                    else
                    {
                        NetworkingManager.Singleton.ConnectedClients[ownerClientId.Value].OwnedObjects.Add(netObject);
                    }
                }
                else if (playerObject && ownerClientId.Value == NetworkingManager.Singleton.LocalClientId)
                {
                    NetworkingManager.Singleton.ConnectedClients[ownerClientId.Value].PlayerObject = netObject;
                }
            }

            if (NetworkingManager.Singleton.IsServer)
            {
                for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++)
                {
                    if (netObject.CheckObjectVisibility == null || netObject.CheckObjectVisibility(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId))
                    {
                        netObject.observers.Add(NetworkingManager.Singleton.ConnectedClientsList[i].ClientId);
                    }
                }
            }

            netObject.ResetNetworkedStartInvoked();

            if (readPayload)
            {
                using (PooledBitStream payloadStream = PooledBitStream.Get())
                {
                    payloadStream.CopyUnreadFrom(dataStream, payloadLength);
                    dataStream.Position   += payloadLength;
                    payloadStream.Position = 0;
                    netObject.InvokeBehaviourNetworkSpawn(payloadStream);
                }
            }
            else
            {
                netObject.InvokeBehaviourNetworkSpawn(null);
            }
        }
示例#15
0
        /// <summary>
        /// Changes the owner of the object. Can only be called from the server or the owner of this Network Behaviour.
        /// </summary>
        /// <param name="targetClientID">The new owner clientId</param>
        public void SetOwner(ulong targetClientID)
        {
            if (!networkManager.isRunning)
            {
                Debug.LogError("Cannot set ownership. The network is not running.");
                return;
            }

            if (!isServer)
            {
                if (isOwner && targetClientID == networkManager.serverID)
                {
                    RemoveOwnership();
                    return;
                }
                throw new NotServerException("Only the server can call NetworkBehaviour.SetOwner to target anything but the server.");
            }

            if (!isNetworkSpawned)
            {
                throw new NetworkException("Cannot change ownership. This Network Behaviour is not spawned.");
            }

            if (!IsNetworkVisibleTo(targetClientID))
            {
                throw new NetworkException("Cannot change ownership to a client that does not have visibility of this Network Behaviour.");
            }

            //Owner does not change
            if (targetClientID == ownerID)
            {
                return;
            }

            if (targetClientID == networkManager.serverID)
            {
                RemoveOwnership();
                return;
            }

            if (isOwner)
            {
                m_OwnerClientID = targetClientID;
                OnLostOwnership();
            }
            else //This may seem redundant but we want ownership changes to be set before the OnLostOwnership call
            {
                m_OwnerClientID = targetClientID;
            }

            //Send to all (not pending)observers
            using (PooledBitStream baseStream = PooledBitStream.Get())
            {
                DoOwnershipWrite(baseStream, targetClientID);
                baseStream.PadStream();

                using (BitStream stream = MessagePacker.WrapMessage(networkBehaviourManager.ownerChangeMessageType, 0, baseStream, SecuritySendFlags.None))
                {
                    using (HashSet <ulong> .Enumerator observers = GetObservers())
                    {
                        while (observers.MoveNext())
                        {
                            if (observers.Current == NetworkManager.Get().serverID)
                            {
                                continue;
                            }

                            NetworkManager.Get().transport.Send(observers.Current, new ArraySegment <byte>(stream.GetBuffer(), 0, (int)stream.Length), networkManager.networkInternalChannel);
                        }
                    }
                }
            }
        }
示例#16
0
        internal static void OnDestroyObject(ulong networkId, bool destroyGameObject)
        {
            if (NetworkingManager.Singleton == null)
            {
                return;
            }

            //Removal of spawned object
            if (!SpawnedObjects.ContainsKey(networkId))
            {
                return;
            }

            if (!SpawnedObjects[networkId].IsOwnedByServer && !SpawnedObjects[networkId].IsPlayerObject &&
                NetworkingManager.Singleton.ConnectedClients.ContainsKey(SpawnedObjects[networkId].OwnerClientId))
            {
                //Someone owns it.
                for (int i = NetworkingManager.Singleton.ConnectedClients[SpawnedObjects[networkId].OwnerClientId].OwnedObjects.Count - 1; i > -1; i--)
                {
                    if (NetworkingManager.Singleton.ConnectedClients[SpawnedObjects[networkId].OwnerClientId].OwnedObjects[i].NetworkId == networkId)
                    {
                        NetworkingManager.Singleton.ConnectedClients[SpawnedObjects[networkId].OwnerClientId].OwnedObjects.RemoveAt(i);
                    }
                }
            }
            SpawnedObjects[networkId].IsSpawned = false;

            if (NetworkingManager.Singleton != null && NetworkingManager.Singleton.IsServer)
            {
                if (NetworkingManager.Singleton.NetworkConfig.RecycleNetworkIds)
                {
                    releasedNetworkObjectIds.Enqueue(new ReleasedNetworkId()
                    {
                        NetworkId   = networkId,
                        ReleaseTime = Time.unscaledTime
                    });
                }

                if (SpawnedObjects[networkId] != null)
                {
                    using (PooledBitStream stream = PooledBitStream.Get())
                    {
                        using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                        {
                            writer.WriteUInt64Packed(networkId);

                            InternalMessageSender.Send(MLAPIConstants.MLAPI_DESTROY_OBJECT, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, SpawnedObjects[networkId]);
                        }
                    }
                }
            }

            GameObject go = SpawnedObjects[networkId].gameObject;

            if (destroyGameObject && go != null)
            {
                if (customDestroyHandlers.ContainsKey(SpawnedObjects[networkId].PrefabHash))
                {
                    customDestroyHandlers[SpawnedObjects[networkId].PrefabHash](SpawnedObjects[networkId]);
                    SpawnManager.OnDestroyObject(networkId, false);
                }
                else
                {
                    MonoBehaviour.Destroy(go);
                }
            }

            SpawnedObjects.Remove(networkId);

            for (int i = SpawnedObjectsList.Count - 1; i > -1; i--)
            {
                if (SpawnedObjectsList[i].NetworkId == networkId)
                {
                    SpawnedObjectsList.RemoveAt(i);
                }
            }
        }
示例#17
0
        private void Update()
        {
            if (isOwner)
            {
                if (NetworkingManager.singleton.NetworkTime - lastSendTime >= (1f / FixedSendsPerSecond) && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees))
                {
                    lastSendTime = NetworkingManager.singleton.NetworkTime;
                    lastSentPos  = transform.position;
                    lastSentRot  = transform.rotation;
                    using (PooledBitStream stream = PooledBitStream.Get())
                    {
                        using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                        {
                            writer.WriteSinglePacked(transform.position.x);
                            writer.WriteSinglePacked(transform.position.y);
                            writer.WriteSinglePacked(transform.position.z);

                            writer.WriteSinglePacked(transform.rotation.eulerAngles.x);
                            writer.WriteSinglePacked(transform.rotation.eulerAngles.y);
                            writer.WriteSinglePacked(transform.rotation.eulerAngles.z);

                            if (isServer)
                            {
                                InvokeClientRpcOnEveryoneExcept(ApplyTransform, OwnerClientId, stream);
                            }
                            else
                            {
                                InvokeServerRpc(SubmitTransform, stream);
                            }
                        }
                    }
                }
            }
            else
            {
                //If we are server and interpolation is turned on for server OR we are not server and interpolation is turned on
                if ((isServer && InterpolateServer && InterpolatePosition) || (!isServer && InterpolatePosition))
                {
                    if (Vector3.Distance(transform.position, lerpEndPos) > SnapDistance)
                    {
                        //Snap, set T to 1 (100% of the lerp)
                        lerpT = 1f;
                    }

                    float sendDelay = (isServer || !EnableRange || !AssumeSyncedSends) ? (1f / FixedSendsPerSecond) : GetTimeForLerp(transform.position, NetworkingManager.singleton.ConnectedClients[NetworkingManager.singleton.LocalClientId].PlayerObject.transform.position);
                    lerpT += Time.time / sendDelay;

                    if (ExtrapolatePosition && Time.time - lastRecieveTime < sendDelay * MaxSendsToExtrapolate)
                    {
                        transform.position = Vector3.LerpUnclamped(lerpStartPos, lerpEndPos, lerpT);
                    }
                    else
                    {
                        transform.position = Vector3.Lerp(lerpStartPos, lerpEndPos, lerpT);
                    }

                    if (ExtrapolatePosition && Time.time - lastRecieveTime < sendDelay * MaxSendsToExtrapolate)
                    {
                        transform.rotation = Quaternion.SlerpUnclamped(lerpStartRot, lerpEndRot, lerpT);
                    }
                    else
                    {
                        transform.rotation = Quaternion.Slerp(lerpStartRot, lerpEndRot, lerpT);
                    }
                }
            }

            if (isServer && EnableRange && EnableNonProvokedResendChecks)
            {
                CheckForMissedSends();
            }
        }
示例#18
0
        // Runs on client
        internal static void HandleHailRequest(ulong clientId, Stream stream)
        {
            X509Certificate2 certificate = null;

            byte[] serverDiffieHellmanPublicPart = null;
            using (PooledBitReader reader = PooledBitReader.Get(stream))
            {
                if (NetworkingManager.Singleton.NetworkConfig.EnableEncryption)
                {
                    // Read the certificate
                    if (NetworkingManager.Singleton.NetworkConfig.SignKeyExchange)
                    {
                        // Allocation justification: This runs on client and only once, at initial connection
                        certificate = new X509Certificate2(reader.ReadByteArray());
                        if (CryptographyHelper.VerifyCertificate(certificate, NetworkingManager.Singleton.ConnectedHostname))
                        {
                            // The certificate is not valid :(
                            // Man in the middle.
                            if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                            {
                                LogHelper.LogWarning("Invalid certificate. Disconnecting");
                            }
                            NetworkingManager.Singleton.StopClient();
                            return;
                        }
                        else
                        {
                            NetworkingManager.Singleton.NetworkConfig.ServerX509Certificate = certificate;
                        }
                    }

                    // Read the ECDH
                    // Allocation justification: This runs on client and only once, at initial connection
                    serverDiffieHellmanPublicPart = reader.ReadByteArray();

                    // Verify the key exchange
                    if (NetworkingManager.Singleton.NetworkConfig.SignKeyExchange)
                    {
                        int signatureType = reader.ReadByte();

                        byte[] serverDiffieHellmanPublicPartSignature = reader.ReadByteArray();

                        if (signatureType == 0)
                        {
                            RSACryptoServiceProvider rsa = certificate.PublicKey.Key as RSACryptoServiceProvider;

                            if (rsa != null)
                            {
                                using (SHA256Managed sha = new SHA256Managed())
                                {
                                    if (!rsa.VerifyData(serverDiffieHellmanPublicPart, sha, serverDiffieHellmanPublicPartSignature))
                                    {
                                        if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                        {
                                            LogHelper.LogWarning("Invalid RSA signature. Disconnecting");
                                        }
                                        NetworkingManager.Singleton.StopClient();
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                {
                                    LogHelper.LogWarning("No RSA key found in certificate. Disconnecting");
                                }
                                NetworkingManager.Singleton.StopClient();
                                return;
                            }
                        }
                        else if (signatureType == 1)
                        {
                            DSACryptoServiceProvider dsa = certificate.PublicKey.Key as DSACryptoServiceProvider;

                            if (dsa != null)
                            {
                                using (SHA256Managed sha = new SHA256Managed())
                                {
                                    if (!dsa.VerifyData(sha.ComputeHash(serverDiffieHellmanPublicPart), serverDiffieHellmanPublicPartSignature))
                                    {
                                        if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                        {
                                            LogHelper.LogWarning("Invalid DSA signature. Disconnecting");
                                        }
                                        NetworkingManager.Singleton.StopClient();
                                        return;
                                    }
                                }
                            }
                            else
                            {
                                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                {
                                    LogHelper.LogWarning("No DSA key found in certificate. Disconnecting");
                                }
                                NetworkingManager.Singleton.StopClient();
                                return;
                            }
                        }
                        else
                        {
                            if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                            {
                                LogHelper.LogWarning("Invalid signature type. Disconnecting");
                            }
                            NetworkingManager.Singleton.StopClient();
                            return;
                        }
                    }
                }
            }

            using (PooledBitStream outStream = PooledBitStream.Get())
            {
                using (PooledBitWriter writer = PooledBitWriter.Get(outStream))
                {
                    if (NetworkingManager.Singleton.NetworkConfig.EnableEncryption)
                    {
                        // Create a ECDH key
                        EllipticDiffieHellman diffieHellman = new EllipticDiffieHellman(EllipticDiffieHellman.DEFAULT_CURVE, EllipticDiffieHellman.DEFAULT_GENERATOR, EllipticDiffieHellman.DEFAULT_ORDER);
                        NetworkingManager.Singleton.clientAesKey = diffieHellman.GetSharedSecret(serverDiffieHellmanPublicPart);
                        byte[] diffieHellmanPublicKey = diffieHellman.GetPublicKey();
                        writer.WriteByteArray(diffieHellmanPublicKey);
                    }
                }

                // Send HailResponse
                InternalMessageSender.Send(NetworkingManager.Singleton.ServerClientId, MLAPIConstants.MLAPI_CERTIFICATE_HAIL_RESPONSE, "MLAPI_INTERNAL", outStream, SecuritySendFlags.None, null);
            }
        }
示例#19
0
        private void SubmitTransform(uint clientId, Stream stream)
        {
            if (!enabled)
            {
                return;
            }
            using (PooledBitReader reader = PooledBitReader.Get(stream))
            {
                float xPos = reader.ReadSinglePacked();
                float yPos = reader.ReadSinglePacked();
                float zPos = reader.ReadSinglePacked();

                float xRot = reader.ReadSinglePacked();
                float yRot = reader.ReadSinglePacked();
                float zRot = reader.ReadSinglePacked();

                if (IsMoveValidDelegate != null && !IsMoveValidDelegate(lerpEndPos, new Vector3(xPos, yPos, zPos)))
                {
                    //Invalid move!
                    //TODO: Add rubber band (just a message telling them to go back)
                    return;
                }

                using (PooledBitStream writeStream = PooledBitStream.Get())
                {
                    using (PooledBitWriter writer = PooledBitWriter.Get(writeStream))
                    {
                        writer.WriteSinglePacked(xPos);
                        writer.WriteSinglePacked(yPos);
                        writer.WriteSinglePacked(zPos);

                        writer.WriteSinglePacked(xRot);
                        writer.WriteSinglePacked(yRot);
                        writer.WriteSinglePacked(zRot);

                        if (EnableRange)
                        {
                            for (int i = 0; i < NetworkingManager.singleton.ConnectedClientsList.Count; i++)
                            {
                                if (!clientSendInfo.ContainsKey(NetworkingManager.singleton.ConnectedClientsList[i].ClientId))
                                {
                                    clientSendInfo.Add(NetworkingManager.singleton.ConnectedClientsList[i].ClientId, new ClientSendInfo()
                                    {
                                        clientId           = NetworkingManager.singleton.ConnectedClientsList[i].ClientId,
                                        lastMissedPosition = null,
                                        lastMissedRotation = null,
                                        lastSent           = 0
                                    });
                                }

                                ClientSendInfo info             = clientSendInfo[NetworkingManager.singleton.ConnectedClientsList[i].ClientId];
                                Vector3        receiverPosition = NetworkingManager.singleton.ConnectedClientsList[i].PlayerObject.transform.position;
                                Vector3        senderPosition   = NetworkingManager.singleton.ConnectedClients[OwnerClientId].PlayerObject.transform.position;

                                if (NetworkingManager.singleton.NetworkTime - info.lastSent >= GetTimeForLerp(receiverPosition, senderPosition))
                                {
                                    info.lastSent           = NetworkingManager.singleton.NetworkTime;
                                    info.lastMissedPosition = null;
                                    info.lastMissedRotation = null;

                                    InvokeClientRpcOnClient(ApplyTransform, NetworkingManager.singleton.ConnectedClientsList[i].ClientId, writeStream);
                                }
                                else
                                {
                                    info.lastMissedPosition = new Vector3(xPos, yPos, zPos);
                                    info.lastMissedRotation = Quaternion.Euler(xRot, yRot, zRot);
                                }
                            }
                        }
                        else
                        {
                            InvokeClientRpcOnEveryoneExcept(ApplyTransform, OwnerClientId, writeStream);
                        }
                    }
                }
            }
        }
示例#20
0
    /// <summary>
    /// this function splits FILES into MEMORY SAFE sized chunks and safely sends one before starting another
    ///
    /// files receipient needs to receive the same number of headers with each header packet (packet 1 counts as a header packet)
    /// </summary>
    public IEnumerator SendFilesDownloadRoutine(string[] _paths, ulong _clientID)
    {
        Debug.Log("coroutine started");
        if (State != LargeRPCState.Idle)
        {
            Debug.LogWarning("Cannot start sending files while files are being sent, waiting for Idle state to begin");
            yield break;
        }

        ReceiverID = _clientID;

        ChangeState(LargeRPCState.Send_SendingHeaders);

        #region comment -- header sizes

        /* -- Header sizes --
         * packet 1
         * int fileCount 4b | long downloadSize 8b | <start headers>
         *
         * header packets
         * int fileID 4b | string filename varsize | byte[256] hash 32b | long fileLength 8b | bool isLastInPacket 1bit
         *
         * subsequent packets
         * int fileID 4b | int filedata_length 4b | byte[var] filedata <=netChunkSize | bool isLastInPacket 1byte
         */
        #endregion

        #region Grab Download Information

        // grab info for headers
        foreach (var path in _paths)
        {
            if (File.Exists(path))
            {
                using (FileStream fs = File.Open(path, FileMode.Open))
                {
                    Debug.Log(fs.Name);
                    int    id       = Headers.Count;
                    byte[] fileHash = fs.sha256();
                    yield return(new WaitForEndOfFrame());

                    FileHeader header = new FileHeader(id, Path.GetFileName(path), fileHash, fs.Length);
                    Headers.Add(header);

                    DownloadSize += header.fileSize;
                }

                // let it exit if it needs to, giving StopRoutine() a chance
                yield return(0);
            }
            else
            {
                Debug.LogWarning("File not found, skipping: " + path);
            }
        }

        #endregion

        #region send headers

        PooledBitStream bitStream = PooledBitStream.Get();
        PooledBitWriter writer    = PooledBitWriter.Get(bitStream);

        // fileCount
        writer.WriteInt32(Headers.Count);

        // downloadSize
        writer.WriteInt64(DownloadSize);


        var headersThisPacket = 0;
        var packetsSent       = 0;
        Debug.Log("Sending headers");
        foreach (var header in Headers)
        {
            // let it exit if it needs to, giving StopRoutine() a chance
            yield return(0);

            Debug.Log(headersThisPacket + "          " + packetsSent);

            var path = header.path;
            var id   = header.id;

            headersThisPacket++;

            // fileID
            writer.WriteInt32(header.id);

            // filename
            writer.WriteString(path);

            Debug.Log(Encoding.Unicode.GetString(header.hash));
            // hash
            writer.WriteByteArray(header.hash, 32);

            // fileLength
            writer.WriteInt64(header.fileSize);

            bool isLastPacket = id >= Headers.Count - 1;

            // send it off if we've filled up a packet
            if (headersThisPacket >= headersPerPacket || isLastPacket)
            {
                Debug.Log("message going out");
                // isLastInPacket
                writer.WriteBit(true);



                CustomMessagingManager.SendNamedMessage(MessageName, _clientID, bitStream, "MLAPI_INTERNAL");

                /* headers are pretty small, they really don't need the receiver to check in here unless it becomes a problem
                 *
                 * // if we haven't sent any packets yet when we get here, wait for an okay from the receiver
                 * if (packetsSent == 0)
                 * {
                 *  ChangeState(LargeRPCState.Send_AwaitingOkayToSend);
                 *
                 *  while (State == LargeRPCState.Send_AwaitingOkayToSend)
                 *  {
                 *      yield return new WaitForSeconds(0.5f);
                 *  }
                 * }*/

                packetsSent++;
                Debug.Log("headers: " + headersThisPacket + "          packets: " + packetsSent);
                headersThisPacket = 0;

                writer.Dispose();
                bitStream.Dispose();

                bitStream = PooledBitStream.Get();
                writer    = PooledBitWriter.Get(bitStream);

                // don't wait on the last one
                if (!isLastPacket)
                {
                    yield return(new WaitForSeconds(1 / 14));
                }
            }
            else
            {
                writer.WriteBit(false);
            }
        }

        writer.Dispose();
        bitStream.Dispose();

        #endregion

        ChangeState(LargeRPCState.Send_AwaitingFilesNeededList);


        ListenForFilesNeededListOrCompletion();

        // loop start
        while (State != LargeRPCState.Complete)
        {
            // let it exit if it needs to, giving StopRoutine() a chance
            yield return(0);

            Debug.Log("Not done, running not-complete loop");
            #region wait for needed files list

            while (State == LargeRPCState.Send_AwaitingFilesNeededList || State == LargeRPCState.Send_EnsuringIntegrity)
            {
                Debug.Log("waiting for list");
                yield return(new WaitForSeconds(0.5f));
            }

            Debug.Log("No longer waiting for list");

            #endregion
            // runs ReceiveFilesNeededListFromReceiver, changes state to either Send_SendingFiles or Complete


            if (filesToSend.Count > 0)
            {
                Debug.Log("client still needs more files, sending");

                #region send files

                bitStream = PooledBitStream.Get();
                writer    = PooledBitWriter.Get(bitStream);

                foreach (var header in Headers)
                {
                    // let it exit if it needs to, giving StopRoutine() a chance
                    yield return(0);

                    Debug.Log("processing header");
                    if (File.Exists(header.path) && filesToSend.Contains(header.id))
                    {
                        Debug.Log("file is needed");
                        using (FileStream fs = File.Open(header.path, FileMode.Open))
                        {
                            // while loop pulled from fs.Read docs from microsoft, a little confusing to the glance but works and will be fast

                            int numBytesToRead = (int)fs.Length;
                            int numBytesRead   = 0;
                            while (numBytesToRead > 0)
                            {
                                Debug.Log("still bytes left");
                                int thisFileChunkSize = fileChunkSize;
                                thisFileChunkSize = Mathf.Min(thisFileChunkSize, numBytesToRead);

                                byte[] fileChunk = new byte[thisFileChunkSize];

                                // Read may return anything from 0 to numBytesToRead.
                                int n = fs.Read(fileChunk, numBytesRead, thisFileChunkSize);



                                foreach (byte[] netChunk in fileChunk.Slices(netChunkSize, false))
                                {
                                    Debug.Log("processing next chunk");

                                    // fileID
                                    writer.WriteInt32(header.id);

                                    //writer.WriteInt32(netChunk.Length);
                                    Debug.Log("netchunk len: " + netChunk.Length);
                                    // filedata
                                    writer.WriteByteArray(netChunk);

                                    // isLastInPacket, need to add in its own size
                                    bool isLastInPacket = bitStream.Length + 1 >= netChunkSize || netChunk.Length < netChunkSize;
                                    writer.WriteBit(isLastInPacket);

                                    if (isLastInPacket)
                                    {
                                        CustomMessagingManager.SendNamedMessage(MessageName, _clientID, bitStream, "MLAPI_INTERNAL");
                                        Debug.Log("packet sent");

                                        yield return(new WaitForSeconds(1 / 14));

                                        writer.Dispose();
                                        bitStream.Dispose();

                                        bitStream = PooledBitStream.Get();
                                        writer    = PooledBitWriter.Get(bitStream);
                                    }
                                }

                                // Break when the end of the file is reached.
                                if (n == 0)
                                {
                                    Debug.Log("end of file reached, this is a failsafe");
                                    break;
                                }

                                numBytesRead   += n;
                                numBytesToRead -= n;
                            }
                        }
                    }
                }

                Debug.Log("all headers processed");

                filesToSend.Clear();

                // just failsafing these, should be disposed of already
                writer.Dispose();
                bitStream.Dispose();

                #endregion

                ChangeState(LargeRPCState.Send_EnsuringIntegrity);
            }

            Debug.Log("Waiting before checking completion again");
            yield return(new WaitForSeconds(1f));
        }

        StopListening();

        Debug.Log("files sent");
        if (OnDownloadComplete != null)
        {
            OnDownloadComplete(SendOrReceiveFlag.Send, ReceiverID);
        }

        ChangeState(LargeRPCState.Idle);

        yield break;
    }
示例#21
0
        // Ran on server
        internal static void HandleHailResponse(uint clientId, Stream stream, int channelId)
        {
            if (!netManager.PendingClients.ContainsKey(clientId) || netManager.PendingClients[clientId].ConnectionState != PendingClient.State.PendingHail)
            {
                return;
            }
            if (!netManager.NetworkConfig.EnableEncryption)
            {
                return;
            }

            using (PooledBitReader reader = PooledBitReader.Get(stream))
            {
                if (NetworkingManager.singleton.PendingClients[clientId].KeyExchange != null)
                {
                    byte[] diffieHellmanPublic = reader.ReadByteArray();
                    netManager.PendingClients[clientId].AesKey = netManager.PendingClients[clientId].KeyExchange.GetSharedSecret(diffieHellmanPublic);
                    if (netManager.NetworkConfig.SignKeyExchange)
                    {
                        byte[]                   diffieHellmanPublicSignature = reader.ReadByteArray();
                        X509Certificate2         certificate = netManager.NetworkConfig.ServerX509Certificate;
                        RSACryptoServiceProvider rsa         = certificate.PrivateKey as RSACryptoServiceProvider;

                        if (rsa != null)
                        {
                            using (SHA256Managed sha = new SHA256Managed())
                            {
                                byte[] clientHash = rsa.Decrypt(diffieHellmanPublicSignature, false);
                                byte[] serverHash = sha.ComputeHash(diffieHellmanPublic);
                                if (clientHash.Length != serverHash.Length)
                                {
                                    //Man in the middle.
                                    if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                    {
                                        if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                        {
                                            LogHelper.LogWarning("Signature length doesnt match for the key exchange public part. Disconnecting");
                                        }
                                    }
                                    netManager.DisconnectClient(clientId);
                                    return;
                                }
                                for (int i = 0; i < clientHash.Length; i++)
                                {
                                    if (clientHash[i] != serverHash[i])
                                    {
                                        //Man in the middle.
                                        if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                        {
                                            if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                                            {
                                                LogHelper.LogWarning("Signature doesnt match for the key exchange public part. Disconnecting");
                                            }
                                        }
                                        netManager.DisconnectClient(clientId);
                                        return;
                                    }
                                }
                            }
                        }
                        else
                        {
                            throw new CryptographicException("[MLAPI] Only RSA certificates are supported. No valid RSA key was found");
                        }
                    }
                }
            }

            netManager.PendingClients[clientId].ConnectionState = PendingClient.State.PendingConnection;
            netManager.PendingClients[clientId].KeyExchange     = null; // Give to GC

            // Send greetings, they have passed all the handshakes
            using (PooledBitStream outStream = PooledBitStream.Get())
            {
                using (PooledBitWriter writer = PooledBitWriter.Get(outStream))
                {
                    writer.WriteInt64Packed(DateTime.Now.Ticks); // This serves no purpose.
                }
                InternalMessageHandler.Send(clientId, MLAPIConstants.MLAPI_GREETINGS, "MLAPI_INTERNAL", outStream, SecuritySendFlags.None, true);
            }
        }
示例#22
0
        private static void OnSceneUnloadServer(Guid switchSceneGuid)
        {
            // Justification: Rare alloc, could(should?) reuse
            List <NetworkedObject> newSceneObjects = new List <NetworkedObject>();

            {
                NetworkedObject[] networkedObjects = MonoBehaviour.FindObjectsOfType <NetworkedObject>();

                for (int i = 0; i < networkedObjects.Length; i++)
                {
                    if (networkedObjects[i].IsSceneObject == null)
                    {
                        SpawnManager.SpawnNetworkedObjectLocally(networkedObjects[i], SpawnManager.GetNetworkObjectId(), true, false, null, null, false, 0, false, true);

                        newSceneObjects.Add(networkedObjects[i]);
                    }
                }
            }


            for (int j = 0; j < NetworkingManager.Singleton.ConnectedClientsList.Count; j++)
            {
                if (NetworkingManager.Singleton.ConnectedClientsList[j].ClientId != NetworkingManager.Singleton.ServerClientId)
                {
                    using (PooledBitStream stream = PooledBitStream.Get())
                    {
                        using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                        {
                            writer.WriteUInt32Packed(CurrentActiveSceneIndex);
                            writer.WriteByteArray(switchSceneGuid.ToByteArray());

                            uint sceneObjectsToSpawn = 0;
                            for (int i = 0; i < newSceneObjects.Count; i++)
                            {
                                if (newSceneObjects[i].observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId))
                                {
                                    sceneObjectsToSpawn++;
                                }
                            }

                            writer.WriteUInt32Packed(sceneObjectsToSpawn);

                            for (int i = 0; i < newSceneObjects.Count; i++)
                            {
                                if (newSceneObjects[i].observers.Contains(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId))
                                {
                                    if (NetworkingManager.Singleton.NetworkConfig.UsePrefabSync)
                                    {
                                        writer.WriteBool(newSceneObjects[i].IsPlayerObject);
                                        writer.WriteUInt64Packed(newSceneObjects[i].NetworkId);
                                        writer.WriteUInt64Packed(newSceneObjects[i].OwnerClientId);

                                        writer.WriteUInt64Packed(newSceneObjects[i].PrefabHash);

                                        writer.WriteSinglePacked(newSceneObjects[i].transform.position.x);
                                        writer.WriteSinglePacked(newSceneObjects[i].transform.position.y);
                                        writer.WriteSinglePacked(newSceneObjects[i].transform.position.z);

                                        writer.WriteSinglePacked(newSceneObjects[i].transform.rotation.eulerAngles.x);
                                        writer.WriteSinglePacked(newSceneObjects[i].transform.rotation.eulerAngles.y);
                                        writer.WriteSinglePacked(newSceneObjects[i].transform.rotation.eulerAngles.z);

                                        if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar)
                                        {
                                            newSceneObjects[i].WriteNetworkedVarData(stream, NetworkingManager.Singleton.ConnectedClientsList[j].ClientId);
                                        }
                                    }
                                    else
                                    {
                                        writer.WriteBool(newSceneObjects[i].IsPlayerObject);
                                        writer.WriteUInt64Packed(newSceneObjects[i].NetworkId);
                                        writer.WriteUInt64Packed(newSceneObjects[i].OwnerClientId);

                                        writer.WriteUInt64Packed(newSceneObjects[i].NetworkedInstanceId);

                                        if (NetworkingManager.Singleton.NetworkConfig.EnableNetworkedVar)
                                        {
                                            newSceneObjects[i].WriteNetworkedVarData(stream, NetworkingManager.Singleton.ConnectedClientsList[j].ClientId);
                                        }
                                    }
                                }
                            }
                        }

                        InternalMessageSender.Send(NetworkingManager.Singleton.ConnectedClientsList[j].ClientId, MLAPIConstants.MLAPI_SWITCH_SCENE, "MLAPI_INTERNAL", stream, SecuritySendFlags.None, null);
                    }
                }
            }

            //Tell server that scene load is completed
            if (NetworkingManager.Singleton.IsHost)
            {
                OnClientSwitchSceneCompleted(NetworkingManager.Singleton.LocalClientId, switchSceneGuid);
            }

            isSwitching = false;

            if (OnSceneSwitched != null)
            {
                OnSceneSwitched();
            }
        }
示例#23
0
        void InvokeApplyTransformOnEveryone(Vector3 position, Quaternion rotation, string channelName)
        {
            using (PooledBitStream stream = PooledBitStream.Get())
            {
                using (PooledBitWriter writer = PooledBitWriter.Get(stream))
                {
                    if (TransformTypeToSync == TransformType.Transform2D)
                    {
                        if (SyncPosition && SyncRotation)
                        {
                            writer.WriteVector2Packed(position);
                            writer.WriteSinglePacked(rotation.eulerAngles.z);
                        }
                        else if (SyncPosition)
                        {
                            writer.WriteVector2Packed(position);
                        }
                        else if (SyncRotation)
                        {
                            writer.WriteSinglePacked(rotation.eulerAngles.z);
                        }
                    }
                    else if (TransformTypeToSync == TransformType.Transform3D)
                    {
                        if (SyncPosition && SyncRotation)
                        {
                            writer.WriteVector3Packed(position);
                            if (FullRotation)
                            {
                                writer.WriteVector3Packed(rotation.eulerAngles);
                            }
                            else
                            {
                                writer.WriteSinglePacked(rotation.eulerAngles.y);
                            }
                        }
                        else if (SyncPosition)
                        {
                            writer.WriteVector3Packed(position);
                        }
                        else if (SyncRotation)
                        {
                            if (FullRotation)
                            {
                                writer.WriteVector3Packed(rotation.eulerAngles);
                            }
                            else
                            {
                                writer.WriteSinglePacked(rotation.eulerAngles.y);
                            }
                        }
                    }

                    if (EnableMinDistanceBetweenClients)
                    {
                        Vector3?senderPosition = transform.position;

                        for (int i = 0; i < NetworkingManager.Singleton.ConnectedClientsList.Count; i++)
                        {
                            Vector3?receiverPosition = NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject == null ? null : new Vector3?(NetworkingManager.Singleton.ConnectedClientsList[i].PlayerObject.transform.position);
                            if (receiverPosition == null || senderPosition == null || Vector3.Distance((Vector3)senderPosition, (Vector3)receiverPosition) < MinDistanceBetweenClients)
                            {
                                InvokeClientRpcOnClientPerformance(TransformTypeToSync == TransformType.Transform2D ? "ApplyTransform2D" : "ApplyTransform", NetworkingManager.Singleton.ConnectedClientsList[i].ClientId, stream, channelName, Security.SecuritySendFlags.None);
                            }
                        }
                    }
                    else
                    {
                        InvokeClientRpcOnEveryonePerformance(TransformTypeToSync == TransformType.Transform2D ? "ApplyTransform2D" : "ApplyTransform", stream, channelName, Security.SecuritySendFlags.None);
                    }
                }
            }
        }