コード例 #1
0
        //Do unspawn on pending behaviour
        //Client only
        private void DoLocalUnspawn(PendingNetworkBehaviour pendingBehaviour, bool destroy)
        {
            if (networkManager.enableLogging)
            {
                Debug.Log("Do Local Unspawn Pending called");
            }
            m_LocalPendingBehaviours.Remove(pendingBehaviour.uniqueHash.Value);

            if (pendingBehaviour.uniqueHash != null)
            {
                m_HashedStrings.Remove(pendingBehaviour.uniqueHash.Value);
                m_BehaviourByHashedID.Remove(pendingBehaviour.uniqueHash.Value);
            }
            m_LocalPendingBehavioursList.Remove(pendingBehaviour.reference.networkBehaviour);

            pendingBehaviour.reference.disconnectedDelegate.Invoke(pendingBehaviour.reference.networkBehaviour.ownerCanUnspawn, destroy);
        }
コード例 #2
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();
                        }
                    }
                }
            }
        }
コード例 #3
0
        //Client only
        public void SpawnOnNetworkClient(NetworkBehaviour behaviour, ClientBehaviourConnectedDelegate connectedCallback, BehaviourDisconnectedDelegate disconnectedCallback, NetworkBehaviourRPCDelegate localRPCCallback, OwnerChangeDelegate ownerChangeCallback)
        {
            if (behaviour == null || !behaviour.isNetworkSpawned || behaviour.isNetworkReady || m_LocalPendingBehavioursList.Contains(behaviour) || string.IsNullOrWhiteSpace(behaviour.uniqueID))
            {
                throw new InvalidOperationException("NetworkBehaviourManager.SpawnNetworkClient is only allowed to be called internally by a Network Behaviour.");
            }

            //Check if this is the Unique Behaviour being spawned in HandleAddObjectMessage where the Unique ID is blank and SpawnOnNetwork is called in Awake.
            if (m_TrackAwakeSpawns)
            {
                m_BehavioursAwaitingSpawn.Enqueue(new NetworkBehaviourReference()
                {
                    networkBehaviour = behaviour, connectedClientCallback = connectedCallback, disconnectedDelegate = disconnectedCallback, localRPCDelegate = localRPCCallback, ownerChangeDelegate = ownerChangeCallback
                });
                return;
            }

            ulong uniqueHash = behaviour.uniqueID.GetStableHash(networkManager.config.rpcHashSize);

            if (m_RemotePendingBehavioursHashes.TryGetValue(uniqueHash, out PendingNetworkBehaviour pendingBehaviour))
            {
                m_RemotePendingBehavioursHashes.Remove(uniqueHash);
                m_RemotePendingBehaviours.Remove(pendingBehaviour.networkID);
                OnObjectConnectSuccess(new NetworkBehaviourReference()
                {
                    networkBehaviour = behaviour, connectedClientCallback = connectedCallback, disconnectedDelegate = disconnectedCallback, localRPCDelegate = localRPCCallback, ownerChangeDelegate = ownerChangeCallback
                }, pendingBehaviour.networkID, pendingBehaviour.ownerID, pendingBehaviour.ownerCanUnspawn, pendingBehaviour.destroyOnUnspawn, pendingBehaviour.spawnPayload);
                pendingBehaviour.spawnPayload?.Dispose();
            }
            else if (m_LocalPendingBehaviours.TryGetValue(uniqueHash, out pendingBehaviour))
            {
                //Check if the unique hash has already been added by this client
                if (m_BehaviourByHashedID.TryGetValue(uniqueHash, out NetworkBehaviour otherBehaviour))
                {
                    if (!BehaviourWasDestroyed(otherBehaviour))
                    {
                        throw new NetworkException("A Network Behaviour already has the unique ID '" + behaviour.uniqueID + "'.");
                    }
                }

                if (m_HashedStrings.TryGetValue(uniqueHash, out string otherUniqueID))
                {
                    if (otherUniqueID == behaviour.uniqueID)
                    {
                        throw new NetworkException("A Network Behaviour already has the unique ID '" + behaviour.uniqueID + "'.");
                    }
                    else
                    {
                        //This occurs when 2 different strings hash to the same value from MLAPI.Hashing.GetStableHash.
                        throw new NetworkException("A hash collision occurred. Either change the unique ID or increase the hash size in the config. '" + behaviour.uniqueID + "' and '" + otherUniqueID + "' both hashed to '" + uniqueHash + "'.");
                    }
                }
            }
            else
            {
                if (m_BehaviourByHashedID.TryGetValue(uniqueHash, out NetworkBehaviour otherBehaviour))
                {
                    if (!BehaviourWasDestroyed(otherBehaviour))
                    {
                        throw new NetworkException("A Network Behaviour already has the unique ID '" + behaviour.uniqueID + "'.");
                    }
                }

                if (m_HashedStrings.TryGetValue(uniqueHash, out string otherUniqueID))
                {
                    if (otherUniqueID == behaviour.uniqueID)
                    {
                        throw new NetworkException("A Network Behaviour already has the unique ID '" + behaviour.uniqueID + "'.");
                    }
                    else
                    {
                        //This occurs when 2 different strings hash to the same value from MLAPI.Hashing.GetStableHash.
                        throw new NetworkException("A hash collision occurred. Either change the unique ID or increase the hash size in the config. '" + behaviour.uniqueID + "' and '" + otherUniqueID + "' both hashed to '" + uniqueHash + "'.");
                    }
                }

                //Add to pending
                pendingBehaviour = new PendingNetworkBehaviour()
                {
                    isRemoteBehaviour = false, uniqueHash = uniqueHash, ownerID = networkManager.serverID, networkID = 0, reference = new NetworkBehaviourReference {
                        networkBehaviour = behaviour, connectedClientCallback = connectedCallback, disconnectedDelegate = disconnectedCallback, localRPCDelegate = localRPCCallback, ownerChangeDelegate = ownerChangeCallback
                    }
                };
                m_LocalPendingBehavioursList.Add(pendingBehaviour.reference.networkBehaviour);
                m_LocalPendingBehaviours.Add(uniqueHash, pendingBehaviour);
                m_HashedStrings.Add(uniqueHash, behaviour.uniqueID);
                m_BehaviourByHashedID.Add(uniqueHash, behaviour);
            }
        }