Example #1
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();
                        }
                    }
                }
            }
        }
Example #2
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.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);
            }
        }
Example #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);
            }
        }