Beispiel #1
0
        /// <summary>
        /// Spawns a object from the pool at a given position and rotation. Can only be called from server.
        /// </summary>
        /// <param name="poolName">The name of the pool</param>
        /// <param name="position">The position to spawn the object at</param>
        /// <param name="rotation">The rotation to spawn the object at</param>
        /// <returns></returns>
        public static GameObject SpawnPoolObject(string poolName, Vector3 position, Quaternion rotation)
        {
            if (!NetworkingManager.singleton.isServer)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Object spawning can only occur on server");
                }
                return(null);
            }
            GameObject go = Pools[PoolNamesToIndexes[poolName]].SpawnObject(position, rotation);

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUInt(go.GetComponent <NetworkedObject>().NetworkId);

                writer.WriteFloat(position.x);
                writer.WriteFloat(position.y);
                writer.WriteFloat(position.z);

                writer.WriteFloat(rotation.eulerAngles.x);
                writer.WriteFloat(rotation.eulerAngles.y);
                writer.WriteFloat(rotation.eulerAngles.z);

                InternalMessageHandler.Send("MLAPI_SPAWN_POOL_OBJECT", "MLAPI_INTERNAL", writer, null);
            }
            return(go);
        }
        internal static void PassthroughSend(uint targetId, uint sourceId, ushort messageType, int channelId, BitReader reader, uint?networkId = null, ushort?orderId = null)
        {
            if (netManager.isHost && targetId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
            {
                //Host trying to send data to it's own client
                return;
            }

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteGenericMessageHeader(messageType, networkId != null, networkId.GetValueOrDefault(), orderId.GetValueOrDefault(), true, null, sourceId);

#if !DISABLE_CRYPTOGRAPHY
                if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(MessageManager.reverseChannels[channelId]))
                {
                    writer.WriteByteArray(CryptographyHelper.Encrypt(reader.ReadByteArray(), netManager.ConnectedClients[targetId].AesKey));
                }
                else
#endif
                writer.WriteByteArray(reader.ReadByteArray());

                writer.Finalize(ref FinalMessageBuffer);

                netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channelId, false, out byte error);
            }
        }
Beispiel #3
0
        internal static void OnDestroyObject(uint networkId, bool destroyGameObject)
        {
            if (!spawnedObjects.ContainsKey(networkId) || (netManager != null && !netManager.NetworkConfig.HandleObjectSpawning))
            {
                return;
            }
            if (spawnedObjects[networkId].OwnerClientId != NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId && !spawnedObjects[networkId].isPlayerObject)
            {
                //Someone owns it.
                NetworkingManager.singleton.connectedClients[spawnedObjects[networkId].OwnerClientId].OwnedObjects.RemoveAll(x => x.NetworkId == networkId);
            }
            GameObject go = spawnedObjects[networkId].gameObject;

            if (netManager != null && netManager.isServer)
            {
                releasedNetworkObjectIds.Push(networkId);
                if (spawnedObjects[networkId] != null)
                {
                    using (BitWriter writer = BitWriter.Get())
                    {
                        writer.WriteUInt(networkId);

                        InternalMessageHandler.Send("MLAPI_DESTROY_OBJECT", "MLAPI_INTERNAL", writer, null);
                    }
                }
            }
            if (destroyGameObject && go != null)
            {
                MonoBehaviour.Destroy(go);
            }
            spawnedObjects.Remove(networkId);
        }
Beispiel #4
0
        /// <summary>
        /// Returns a base64 encoded version of the config
        /// </summary>
        /// <returns></returns>
        public string ToBase64()
        {
            NetworkConfig config = this;

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUShort(config.ProtocolVersion);
                writer.WriteBits((byte)config.Transport, 5);

                writer.WriteUShort((ushort)config.Channels.Count);
                for (int i = 0; i < config.Channels.Count; i++)
                {
                    writer.WriteString(config.Channels[i].Name);
                    writer.WriteBool(config.Channels[i].Encrypted);
                    writer.WriteBits((byte)config.Channels[i].Type, 5);
                }

                writer.WriteUShort((ushort)config.MessageTypes.Count);
                for (int i = 0; i < config.MessageTypes.Count; i++)
                {
                    writer.WriteString(config.MessageTypes[i].Name);
                    writer.WriteBool(config.MessageTypes[i].Passthrough);
                }

                writer.WriteUShort((ushort)config.RegisteredScenes.Count);
                for (int i = 0; i < config.RegisteredScenes.Count; i++)
                {
                    writer.WriteString(config.RegisteredScenes[i]);
                }

                writer.WriteUShort((ushort)config.NetworkedPrefabs.Count);
                for (int i = 0; i < config.NetworkedPrefabs.Count; i++)
                {
                    writer.WriteBool(config.NetworkedPrefabs[i].playerPrefab);
                    writer.WriteString(config.NetworkedPrefabs[i].name);
                }

                writer.WriteInt(config.MessageBufferSize);
                writer.WriteInt(config.ReceiveTickrate);
                writer.WriteInt(config.MaxReceiveEventsPerTickRate);
                writer.WriteInt(config.SendTickrate);
                writer.WriteInt(config.EventTickrate);
                writer.WriteInt(config.MaxConnections);
                writer.WriteInt(config.ConnectPort);
                writer.WriteString(config.ConnectAddress);
                writer.WriteInt(config.ClientConnectionBufferTimeout);
                writer.WriteBool(config.ConnectionApproval);
                writer.WriteInt(config.SecondsHistory);
                writer.WriteBool(config.HandleObjectSpawning);
                writer.WriteBool(config.EnableEncryption);
                writer.WriteBool(config.SignKeyExchange);
                writer.WriteBool(config.AllowPassthroughMessages);
                writer.WriteBool(config.EnableSceneSwitching);
                writer.WriteBool(config.EnableTimeResync);
                writer.WriteBits((byte)config.AttributeMessageMode, 3);

                return(Convert.ToBase64String(writer.Finalize()));
            }
        }
Beispiel #5
0
        /// <summary>
        /// Gets a SHA256 hash of parts of the NetworkingConfiguration instance
        /// </summary>
        /// <param name="cache"></param>
        /// <returns></returns>
        public ulong GetConfig(bool cache = true)
        {
            if (ConfigHash != null && cache)
            {
                return(ConfigHash.Value);
            }

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUShort(ProtocolVersion);
                for (int i = 0; i < Channels.Count; i++)
                {
                    writer.WriteString(Channels[i].Name);
                    writer.WriteByte((byte)Channels[i].Type);
                    if (EnableEncryption)
                    {
                        writer.WriteBool(Channels[i].Encrypted);
                    }
                }
                for (int i = 0; i < MessageTypes.Count; i++)
                {
                    writer.WriteString(MessageTypes[i].Name);
                    if (AllowPassthroughMessages)
                    {
                        writer.WriteBool(MessageTypes[i].Passthrough);
                    }
                }
                if (EnableSceneSwitching)
                {
                    for (int i = 0; i < RegisteredScenes.Count; i++)
                    {
                        writer.WriteString(RegisteredScenes[i]);
                    }
                }
                if (HandleObjectSpawning)
                {
                    for (int i = 0; i < NetworkedPrefabs.Count; i++)
                    {
                        writer.WriteString(NetworkedPrefabs[i].name);
                    }
                }
                writer.WriteBool(HandleObjectSpawning);
                writer.WriteBool(EnableEncryption);
                writer.WriteBool(AllowPassthroughMessages);
                writer.WriteBool(EnableSceneSwitching);
                writer.WriteBool(SignKeyExchange);
                writer.WriteBits((byte)AttributeMessageMode, 3);

                // Returns a 160 bit / 20 byte / 5 int checksum of the config
                if (cache)
                {
                    ConfigHash = writer.Finalize().GetStableHash64();
                    return(ConfigHash.Value);
                }
                return(writer.Finalize().GetStableHash64());
            }
        }
Beispiel #6
0
        internal string ToBase64()
        {
            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUShort(ProtocolVersion);
                writer.WriteBits((byte)Transport, 5);

                writer.WriteUShort((ushort)Channels.Count);
                for (int i = 0; i < Channels.Count; i++)
                {
                    writer.WriteString(Channels[i].Name);
                    writer.WriteBool(Channels[i].Encrypted);
                    writer.WriteBits((byte)Channels[i].Type, 5);
                }

                writer.WriteUShort((ushort)MessageTypes.Count);
                for (int i = 0; i < MessageTypes.Count; i++)
                {
                    writer.WriteString(MessageTypes[i].Name);
                    writer.WriteBool(MessageTypes[i].Passthrough);
                }

                writer.WriteUShort((ushort)RegisteredScenes.Count);
                for (int i = 0; i < RegisteredScenes.Count; i++)
                {
                    writer.WriteString(RegisteredScenes[i]);
                }

                writer.WriteUShort((ushort)NetworkedPrefabs.Count);
                for (int i = 0; i < NetworkedPrefabs.Count; i++)
                {
                    writer.WriteBool(NetworkedPrefabs[i].playerPrefab);
                    writer.WriteString(NetworkedPrefabs[i].name);
                }

                writer.WriteInt(MessageBufferSize);
                writer.WriteInt(ReceiveTickrate);
                writer.WriteInt(MaxReceiveEventsPerTickRate);
                writer.WriteInt(SendTickrate);
                writer.WriteInt(EventTickrate);
                writer.WriteInt(MaxConnections);
                writer.WriteInt(ConnectPort);
                writer.WriteString(ConnectAddress);
                writer.WriteInt(ClientConnectionBufferTimeout);
                writer.WriteBool(ConnectionApproval);
                writer.WriteInt(SecondsHistory);
                writer.WriteBool(HandleObjectSpawning);
                writer.WriteBool(EnableEncryption);
                writer.WriteBool(SignKeyExchange);
                writer.WriteBool(AllowPassthroughMessages);
                writer.WriteBool(EnableSceneSwitching);
                writer.WriteBool(EnableTimeResync);
                writer.WriteBits((byte)AttributeMessageMode, 3);

                return(Convert.ToBase64String(writer.Finalize()));
            }
        }
Beispiel #7
0
        //RETURNS THE CLIENTIDS WHICH WAS NOT BEING OBSERVED
        internal static ref List <uint> Send(string messageType, string channelName, BitWriter messageWriter, uint clientIdToIgnore, uint?fromNetId, uint?networkId = null, ushort?orderId = null)
        {
            failedObservers.Clear();
            if (netManager.NetworkConfig.EncryptedChannels.Contains(channelName))
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Cannot send messages over encrypted channel to multiple clients");
                }
                return(ref failedObservers);
            }

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteGenericMessageHeader(MessageManager.messageTypes[messageType], networkId != null, networkId.GetValueOrDefault(), orderId.GetValueOrDefault(), false, 0, 0);

                writer.WriteWriter(messageWriter);

                int channel = MessageManager.channels[channelName];
                foreach (KeyValuePair <uint, NetworkedClient> pair in netManager.connectedClients)
                {
                    if (pair.Key == clientIdToIgnore)
                    {
                        continue;
                    }

                    uint targetClientId = pair.Key;
                    if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
                    {
                        //Don't invoke the message on our own machine. Instant stack overflow.
                        continue;
                    }
                    else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
                    {
                        //Client trying to send data to host
                        targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId;
                    }

                    //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we continue
                    if (netManager.isServer && fromNetId != null && !SpawnManager.spawnedObjects[fromNetId.Value].observers.Contains(pair.Key))
                    {
                        failedObservers.Add(pair.Key);
                        continue;
                    }

                    writer.Finalize(ref FinalMessageBuffer);

                    NetworkProfiler.StartEvent(TickType.Send, (uint)messageWriter.GetFinalizeSize(), channelName, messageType);
                    byte error;
                    int  byteCount = (int)writer.GetFinalizeSize();
                    NetworkProfiler.addBytesSent((uint)byteCount);
                    netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, byteCount, channel, false, out error);
                    NetworkProfiler.EndEvent();
                }
                return(ref failedObservers);
            }
        }
Beispiel #8
0
        public void TestWritingTrue()
        {
            BitWriter bitWriter = BitWriter.Get();

            bitWriter.WriteBool(true);

            byte[] result = bitWriter.Finalize();

            Assert.That(result.Length, Is.EqualTo(1));
            Assert.That(result[0], Is.EqualTo(1));
        }
Beispiel #9
0
        internal static void FlushSceneObjects()
        {
            if (!NetworkingManager.singleton.isServer)
            {
                return;
            }

            //This loop is bad. For each client, we loop over every object twice.
            foreach (KeyValuePair <uint, NetworkedClient> client in netManager.connectedClients)
            {
                int sceneObjects = 0;
                foreach (var netObject in SpawnManager.spawnedObjects)
                {
                    if (netObject.Value.sceneObject == null || netObject.Value.sceneObject == true)
                    {
                        sceneObjects++;
                    }
                }

                using (BitWriter writer = BitWriter.Get())
                {
                    writer.WriteUShort((ushort)sceneObjects);
                    foreach (var netObject in SpawnManager.spawnedObjects)
                    {
                        if (netObject.Value.sceneObject == null || netObject.Value.sceneObject == true)
                        {
                            writer.WriteBool(false); //isLocalPlayer
                            writer.WriteUInt(netObject.Value.NetworkId);
                            writer.WriteUInt(netObject.Value.OwnerClientId);
                            writer.WriteInt(NetworkingManager.singleton.NetworkConfig.NetworkPrefabIds[netObject.Value.NetworkedPrefabName]);
                            writer.WriteBool(netObject.Value.sceneObject == null ? true : netObject.Value.sceneObject.Value);
                            writer.WriteBool(netObject.Value.observers.Contains(client.Key));

                            writer.WriteFloat(netObject.Value.transform.position.x);
                            writer.WriteFloat(netObject.Value.transform.position.y);
                            writer.WriteFloat(netObject.Value.transform.position.z);

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

                            if (netObject.Value.observers.Contains(client.Key))
                            {
                                netObject.Value.WriteFormattedSyncedVarData(writer);
                            }
                        }
                    }
                    InternalMessageHandler.Send(client.Key, "MLAPI_ADD_OBJECTS", "MLAPI_INTERNAL", writer, null);
                }
            }
        }
Beispiel #10
0
        internal static void Send(uint[] clientIds, string messageType, string channelName, BitWriter messageWriter, uint?fromNetId, uint?networkId = null, ushort?orderId = null)
        {
            if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(channelName))
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Cannot send messages over encrypted channel to multiple clients");
                }
                return;
            }

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteGenericMessageHeader(MessageManager.messageTypes[messageType], networkId != null, networkId.GetValueOrDefault(), orderId.GetValueOrDefault(), false, 0, 0);

                writer.WriteWriter(messageWriter);

                int channel = MessageManager.channels[channelName];
                for (int i = 0; i < clientIds.Length; i++)
                {
                    uint targetClientId = clientIds[i];
                    if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
                    {
                        //Don't invoke the message on our own machine. Instant stack overflow.
                        continue;
                    }
                    else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
                    {
                        //Client trying to send data to host
                        targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId;
                    }

                    //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we continue
                    if (netManager.isServer && fromNetId != null && !SpawnManager.spawnedObjects[fromNetId.Value].observers.Contains(clientIds[i]))
                    {
                        continue;
                    }

                    writer.Finalize(ref FinalMessageBuffer);

                    NetworkProfiler.StartEvent(TickType.Send, (uint)messageWriter.GetFinalizeSize(), channelName, messageType);
                    byte error;
                    netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), channel, false, out error);
                    NetworkProfiler.EndEvent();
                }
            }
        }
Beispiel #11
0
        /// <summary>
        /// Destroys a NetworkedObject if it's part of a pool. Use this instead of the MonoBehaviour Destroy method. Can only be called from Server.
        /// </summary>
        /// <param name="netObject">The NetworkedObject instance to destroy</param>
        public static void DestroyPoolObject(NetworkedObject netObject)
        {
            if (!NetworkingManager.singleton.isServer)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Objects can only be destroyed on the server");
                }
                return;
            }
            netObject.gameObject.SetActive(false);
            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUInt(netObject.NetworkId);

                InternalMessageHandler.Send("MLAPI_DESTROY_POOL_OBJECT", "MLAPI_INTERNAL", writer, null);
            }
        }
        /// <summary>
        /// Switches to a scene with a given name. Can only be called from Server
        /// </summary>
        /// <param name="sceneName">The name of the scene to switch to</param>
        public static void SwitchScene(string sceneName)
        {
            if (!NetworkingManager.singleton.NetworkConfig.EnableSceneSwitching)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Scene switching is not enabled");
                }
                return;
            }
            else if (isSwitching)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("Scene switch already in progress");
                }
                return;
            }
            else if (!registeredSceneNames.Contains(sceneName))
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("The scene " + sceneName + " is not registered as a switchable scene.");
                }
                return;
            }
            SpawnManager.DestroySceneObjects(); //Destroy current scene objects before switching.
            CurrentSceneIndex = sceneNameToIndex[sceneName];
            isSwitching       = true;
            lastScene         = SceneManager.GetActiveScene();
            AsyncOperation sceneLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);

            sceneLoad.completed += OnSceneLoaded;

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUInt(sceneNameToIndex[sceneName]);

                InternalMessageHandler.Send("MLAPI_SWITCH_SCENE", "MLAPI_INTERNAL", writer, null);
            }
        }
Beispiel #13
0
        internal static void RemoveOwnership(uint netId)
        {
            if (!netManager.isServer)
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("You can only remove ownership from Server");
                }
                return;
            }
            NetworkedObject netObject = SpawnManager.spawnedObjects[netId];

            NetworkingManager.singleton.connectedClients[netObject.OwnerClientId].OwnedObjects.RemoveAll(x => x.NetworkId == netId);
            netObject.ownerClientId = NetworkingManager.singleton.NetworkConfig.NetworkTransport.InvalidDummyId;

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteUInt(netId);
                writer.WriteUInt(netObject.ownerClientId);

                InternalMessageHandler.Send("MLAPI_CHANGE_OWNER", "MLAPI_INTERNAL", writer, null);
            }
        }
        //RETURNS IF IT SUCCEDED OR FAILED BECAUSE OF NON-OBSERVER. ANY OTHER FAIL WILL RETURN TRUE
        internal static bool Send(uint clientId, string messageType, string channelName, BitWriter messageWriter, uint?fromNetId, uint?networkId = null, ushort?orderId = null, bool skipQueue = false)
        {
            uint targetClientId = clientId;

            if (netManager.isHost && targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
            {
                //Don't invoke the message on our own machine. Instant stack overflow.
                return(true);
            }
            else if (targetClientId == netManager.NetworkConfig.NetworkTransport.HostDummyId)
            {
                //Client trying to send data to host
                targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId;
            }
            //If we respect the observers, and the message is targeted (networkId != null) and the targetedNetworkId isnt observing the receiver. Then we return
            if (netManager.isServer && fromNetId != null && !SpawnManager.spawnedObjects[fromNetId.Value].observers.Contains(clientId))
            {
                return(false);
            }

            bool isPassthrough = (!netManager.isServer && clientId != netManager.NetworkConfig.NetworkTransport.ServerNetId && netManager.NetworkConfig.AllowPassthroughMessages);

            if (isPassthrough && !netManager.NetworkConfig.PassthroughMessageHashSet.Contains(MessageManager.messageTypes[messageType]))
            {
                if (LogHelper.CurrentLogLevel <= LogLevel.Normal)
                {
                    LogHelper.LogWarning("The The MessageType " + messageType + " is not registered as an allowed passthrough message type");
                }
                return(true);
            }

            using (BitWriter writer = BitWriter.Get())
            {
                writer.WriteGenericMessageHeader(MessageManager.messageTypes[messageType], networkId != null, networkId.GetValueOrDefault(), orderId.GetValueOrDefault(), isPassthrough, clientId, null);

#if !DISABLE_CRYPTOGRAPHY
                if (netManager.NetworkConfig.EncryptedChannelsHashSet.Contains(channelName))
                {
                    //This is an encrypted message.
                    byte[] encrypted;
                    if (netManager.isServer)
                    {
                        encrypted = CryptographyHelper.Encrypt(messageWriter.Finalize(), netManager.ConnectedClients[clientId].AesKey);
                    }
                    else
                    {
                        encrypted = CryptographyHelper.Encrypt(messageWriter.Finalize(), netManager.clientAesKey);
                    }

                    writer.WriteByteArray(encrypted);
                }
                else
#endif
                writer.WriteWriter(messageWriter);

                if (isPassthrough)
                {
                    targetClientId = netManager.NetworkConfig.NetworkTransport.ServerNetId;
                }

                writer.Finalize(ref FinalMessageBuffer);

                NetworkProfiler.StartEvent(TickType.Send, (uint)messageWriter.GetFinalizeSize(), channelName, messageType);
                byte error;
                if (skipQueue)
                {
                    netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), MessageManager.channels[channelName], true, out error);
                }
                else
                {
                    netManager.NetworkConfig.NetworkTransport.QueueMessageForSending(targetClientId, ref FinalMessageBuffer, (int)writer.GetFinalizeSize(), MessageManager.channels[channelName], false, out error);
                }
                NetworkProfiler.EndEvent();

                return(true);
            }
        }
Beispiel #15
0
        internal void RebuildObservers(uint?clientId = null)
        {
            bool initial = clientId != null;

            if (initial)
            {
                bool shouldBeAdded = true;
                for (int i = 0; i < childNetworkedBehaviours.Count; i++)
                {
                    bool state = childNetworkedBehaviours[i].OnCheckObserver(clientId.Value);
                    if (state == false)
                    {
                        shouldBeAdded = false;
                        break;
                    }
                }
                if (shouldBeAdded)
                {
                    observers.Add(clientId.Value);
                }
            }
            else
            {
                previousObservers.Clear();
                foreach (var item in observers)
                {
                    previousObservers.Add(item);
                }
                bool update = false;
                for (int i = 0; i < childNetworkedBehaviours.Count; i++)
                {
                    bool changed = childNetworkedBehaviours[i].OnRebuildObservers(observers);
                    if (changed)
                    {
                        update = true;
                        break;
                    }
                }
                if (update)
                {
                    foreach (KeyValuePair <uint, NetworkedClient> pair in NetworkingManager.singleton.connectedClients)
                    {
                        if (pair.Key == NetworkingManager.singleton.NetworkConfig.NetworkTransport.HostDummyId)
                        {
                            continue;
                        }
                        if ((previousObservers.Contains(pair.Key) && !observers.Contains(pair.Key)) ||
                            (!previousObservers.Contains(pair.Key) && observers.Contains(pair.Key)))
                        {
                            //Something changed for this client.
                            using (BitWriter writer = BitWriter.Get())
                            {
                                writer.WriteUInt(networkId);
                                writer.WriteBool(observers.Contains(pair.Key));

                                if (observers.Contains(pair.Key))
                                {
                                    WriteFormattedSyncedVarData(writer);
                                }

                                InternalMessageHandler.Send(pair.Key, "MLAPI_SET_VISIBILITY", "MLAPI_INTERNAL", writer, null);
                            }
                        }
                    }
                }
                else
                {
                    foreach (var item in previousObservers)
                    {
                        observers.Add(item);
                    }
                }
                previousObservers.Clear();
            }
        }
Beispiel #16
0
        internal static void SpawnObject(NetworkedObject netObject, uint?clientOwnerId = null, BitWriter 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);
            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
            {
                using (BitReader payloadReader = BitReader.Get(payload.Finalize())) netObject.InvokeBehaviourNetworkSpawn(payloadReader);
            }

            foreach (var client in netManager.connectedClients)
            {
                netObject.RebuildObservers(client.Key);
                using (BitWriter writer = BitWriter.Get())
                {
                    writer.WriteBool(false);
                    writer.WriteUInt(netObject.NetworkId);
                    writer.WriteUInt(netObject.OwnerClientId);
                    writer.WriteInt(netManager.NetworkConfig.NetworkPrefabIds[netObject.NetworkedPrefabName]);
                    writer.WriteBool(netObject.sceneObject == null ? true : netObject.sceneObject.Value);
                    writer.WriteBool(netObject.observers.Contains(client.Key));

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

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

                    writer.WriteBool(payload != null);

                    if (netObject.observers.Contains(client.Key))
                    {
                        netObject.WriteFormattedSyncedVarData(writer);
                    }

                    if (payload != null)
                    {
                        writer.WriteWriter(payload);
                    }

                    InternalMessageHandler.Send(client.Key, "MLAPI_ADD_OBJECT", "MLAPI_INTERNAL", writer, null);
                }
            }
        }