Ejemplo n.º 1
0
        void CheckSendRate()
        {
            if (SendMessagesAllowed && syncInterval > 0 && sendTimer < Time.time)
            {
                sendTimer = Time.time + syncInterval;

                using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
                {
                    if (WriteParameters(writer))
                    {
                        SendAnimationParametersMessage(writer.ToArray());
                    }
                }
            }
        }
 private void PushLength(int length, ref PooledNetworkWriter writer)
 {
     // If length is single byte we write it
     if (length < 256)
     {
         writer.WriteByte((byte)length); // write the amounts of bytes that are coming up
     }
     else
     {
         // otherwise we write a two-byte length
         writer.WriteByte(k_LongLenMarker);      // mark larger size
         writer.WriteByte((byte)(length % 256)); // write the length modulo 256
         writer.WriteByte((byte)(length / 256)); // write the length divided by 256
     }
 }
Ejemplo n.º 3
0
        public void PoolCanGetMoreWritersThanPoolSize()
        {
            NetworkWriterPool.Capacity = 5;

            const int testWriterCount = 10;
            var       writers         = new PooledNetworkWriter[testWriterCount];

            for (int i = 0; i < testWriterCount; i++)
            {
                writers[i] = NetworkWriterPool.GetWriter();
            }

            // Make sure all writers are different
            Assert.That(writers.Distinct().Count(), Is.EqualTo(testWriterCount));
        }
        /// <summary>
        /// Gets a SHA256 hash of parts of the NetworkConfig instance
        /// </summary>
        /// <param name="cache"></param>
        /// <returns></returns>
        public ulong GetConfig(bool cache = true)
        {
            if (m_ConfigHash != null && cache)
            {
                return(m_ConfigHash.Value);
            }

            Sort();

            using (var buffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(buffer))
                {
                    writer.WriteUInt16Packed(ProtocolVersion);
                    writer.WriteString(NetworkConstants.PROTOCOL_VERSION);

                    if (EnableSceneManagement && !AllowRuntimeSceneChanges)
                    {
                        for (int i = 0; i < RegisteredScenes.Count; i++)
                        {
                            writer.WriteString(RegisteredScenes[i]);
                        }
                    }

                    if (ForceSamePrefabs)
                    {
                        var sortedDictionary = NetworkPrefabOverrideLinks.OrderBy(x => x.Key);
                        foreach (var sortedEntry in sortedDictionary)
                        {
                            writer.WriteUInt32Packed(sortedEntry.Key);
                        }
                    }

                    writer.WriteBool(EnableNetworkVariable);
                    writer.WriteBool(ForceSamePrefabs);
                    writer.WriteBool(EnableSceneManagement);
                    writer.WriteBool(EnsureNetworkVariableLengthSafety);
                    writer.WriteBits((byte)RpcHashSize, 2);
                    buffer.PadBuffer();

                    if (cache)
                    {
                        m_ConfigHash = XXHash.Hash64(buffer.ToArray());
                        return(m_ConfigHash.Value);
                    }

                    return(XXHash.Hash64(buffer.ToArray()));
                }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// This function invokes the registered handler function for a message.
        /// <para>Network connections used by the NetworkClient and NetworkServer use this function for handling network messages.</para>
        /// </summary>
        /// <typeparam name="T">The message type to unregister.</typeparam>
        /// <param name="msg">The message object to process.</param>
        /// <returns>Returns true if the handler was successfully invoked</returns>
        public bool InvokeHandler<T>(T msg, int channelId) where T :struct, NetworkMessage
        {
            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                // if it is a value type,  just use typeof(T) to avoid boxing
                // this works because value types cannot be derived
                // if it is a reference type (for example NetworkMessage),
                // ask the message for the real type
                int msgType = MessagePacker.GetId<T>();

                MessagePacker.Pack(msg, writer);
                ArraySegment<byte> segment = writer.ToArraySegment();
                using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(segment))
                    return InvokeHandler(msgType, networkReader, channelId);
            }
        }
Ejemplo n.º 6
0
        internal static void WriteNetworkVariableData(List <INetworkVariable> networkVariableList, Stream stream, ulong clientId, NetworkManager networkManager)
        {
            if (networkVariableList.Count == 0)
            {
                return;
            }

            using (var writer = PooledNetworkWriter.Get(stream))
            {
                for (int j = 0; j < networkVariableList.Count; j++)
                {
                    bool canClientRead = networkVariableList[j].CanClientRead(clientId);

                    if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
                    {
                        if (!canClientRead)
                        {
                            writer.WriteUInt16Packed(0);
                        }
                    }
                    else
                    {
                        writer.WriteBool(canClientRead);
                    }

                    if (canClientRead)
                    {
                        if (networkManager.NetworkConfig.EnsureNetworkVariableLengthSafety)
                        {
                            using (var varBuffer = PooledNetworkBuffer.Get())
                            {
                                networkVariableList[j].WriteField(varBuffer);
                                varBuffer.PadBuffer();

                                writer.WriteUInt16Packed((ushort)varBuffer.Length);
                                varBuffer.CopyTo(stream);
                            }
                        }
                        else
                        {
                            networkVariableList[j].WriteField(stream);
                        }
                    }
                }
            }
        }
Ejemplo n.º 7
0
        /// <inheritdoc />
        public void WriteDelta(Stream stream)
        {
            using (var writer = PooledNetworkWriter.Get(stream))
            {
                writer.WriteUInt16Packed((ushort)m_DirtyEvents.Count);
                for (int i = 0; i < m_DirtyEvents.Count; i++)
                {
                    writer.WriteBits((byte)m_DirtyEvents[i].Type, 3);
                    switch (m_DirtyEvents[i].Type)
                    {
                    case NetworkDictionaryEvent <TKey, TValue> .EventType.Add:
                    {
                        writer.WriteObjectPacked(m_DirtyEvents[i].Key);
                        writer.WriteObjectPacked(m_DirtyEvents[i].Value);
                    }
                    break;

                    case NetworkDictionaryEvent <TKey, TValue> .EventType.Remove:
                    {
                        writer.WriteObjectPacked(m_DirtyEvents[i].Key);
                    }
                    break;

                    case NetworkDictionaryEvent <TKey, TValue> .EventType.RemovePair:
                    {
                        writer.WriteObjectPacked(m_DirtyEvents[i].Key);
                        writer.WriteObjectPacked(m_DirtyEvents[i].Value);
                    }
                    break;

                    case NetworkDictionaryEvent <TKey, TValue> .EventType.Clear:
                    {
                        //write nothing
                    }
                    break;

                    case NetworkDictionaryEvent <TKey, TValue> .EventType.Value:
                    {
                        writer.WriteObjectPacked(m_DirtyEvents[i].Key);
                        writer.WriteObjectPacked(m_DirtyEvents[i].Value);
                    }
                    break;
                    }
                }
            }
        }
Ejemplo n.º 8
0
    public void SumOnServer(byte[] serverReceivedData)
    {
        PooledNetworkReader pooledNetworkReader = NetworkReaderPool.GetReader(serverReceivedData);
        int a = pooledNetworkReader.Read <int>();
        int b = pooledNetworkReader.Read <int>();

        pooledNetworkReader.Dispose();
        PooledNetworkWriter pooledNetworkWriter = NetworkWriterPool.GetWriter();
        int result = a + b;

        pooledNetworkWriter.Write(result);
        pooledNetworkWriter.ToArray();
        byte[] dataToSendClient = pooledNetworkWriter.ToArray();
        Debug.LogWarning("Server " + result);
        RpcReceive(DataCommand.TEST_SumOnServer, dataToSendClient);
        pooledNetworkWriter.Dispose();
    }
        public void SendMaxBatchSizedMessageBatch()
        {
            // create a message == max batch size
            int max = transport.GetMaxBatchSize(Channels.DefaultReliable);

            byte[] message = new byte[max];

            // add to batch queue
            PooledNetworkWriter writer = NetworkWriterPool.GetWriter();

            writer.WriteBytes(message, 0, message.Length);
            batch.messages.Enqueue(writer);

            // send batch - client should receive that exact message
            connection.SendBatch(Channels.DefaultReliable, batch);
            Assert.That(transport.clientIncoming.Count, Is.EqualTo(1));
            Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
        }
Ejemplo n.º 10
0
 public void C2SSceneChanged(int newScene)
 {
     if (NetManager.IsHost)
     {
         ClientSceneChanged?.Invoke(NetManager.ServerClientId, newScene);
     }
     else if (NetManager.IsConnectedClient)
     {
         using (var buffer = PooledNetworkBuffer.Get())
         {
             using (var writer = PooledNetworkWriter.Get(buffer))
             {
                 writer.WriteInt32(newScene);
                 MLAPI.Messaging.CustomMessagingManager.SendNamedMessage("C2S_SceneChanged", NetManager.ServerClientId, buffer, NetworkChannel.Internal);
             }
         }
     }
 }
Ejemplo n.º 11
0
        /// <summary>
        /// Send fake values to client's <see cref="Mirror.SyncVarAttribute"/>.
        /// </summary>
        /// <param name="target">Target to send.</param>
        /// <param name="behaviorOwner"><see cref="Mirror.NetworkIdentity"/> of object that owns <see cref="Mirror.NetworkBehaviour"/>.</param>
        /// <param name="targetType"><see cref="Mirror.NetworkBehaviour"/>'s type.</param>
        /// <param name="propertyName">Property name starting with Network.</param>
        /// <param name="value">Value of send to target.</param>
        public static void SendFakeSyncVar(this Player target, NetworkIdentity behaviorOwner, Type targetType, string propertyName, object value)
        {
            void CustomSyncVarGenerator(NetworkWriter targetWriter)
            {
                targetWriter.WriteUInt64(SyncVarDirtyBits[$"{propertyName}"]);
                WriterExtensions[value.GetType()]?.Invoke(null, new object[] { targetWriter, value });
            }

            PooledNetworkWriter writer  = NetworkWriterPool.GetWriter();
            PooledNetworkWriter writer2 = NetworkWriterPool.GetWriter();

            MakeCustomSyncWriter(behaviorOwner, targetType, null, CustomSyncVarGenerator, writer, writer2);
            target.ReferenceHub.networkIdentity.connectionToClient.Send(new UpdateVarsMessage()
            {
                netId = behaviorOwner.netId, payload = writer.ToArraySegment()
            });
            NetworkWriterPool.Recycle(writer);
            NetworkWriterPool.Recycle(writer2);
        }
Ejemplo n.º 12
0
        public void SyncVarIsBitPacked()
        {
            serverComponent.myValue = value;

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                serverComponent.SerializeSyncVars(writer, true);

                Assert.That(writer.BitPosition, Is.EqualTo(32));

                using (PooledNetworkReader reader = NetworkReaderPool.GetReader(writer.ToArraySegment(), null))
                {
                    clientComponent.DeserializeSyncVars(reader, true);
                    Assert.That(reader.BitPosition, Is.EqualTo(32));

                    Assert.That(clientComponent.myValue, Is.EqualTo(value));
                }
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Hides a list of objects from a client
        /// </summary>
        /// <param name="networkObjects">The objects to hide</param>
        /// <param name="clientId">The client to hide the objects from</param>
        public static void NetworkHide(List <NetworkObject> networkObjects, ulong clientId)
        {
            if (!NetworkManager.Singleton.IsServer)
            {
                throw new NotServerException("Only server can change visibility");
            }

            if (clientId == NetworkManager.Singleton.ServerClientId)
            {
                throw new VisibilityChangeException("Cannot hide an object from the server");
            }

            // Do the safety loop first to prevent putting the MLAPI in an invalid state.
            for (int i = 0; i < networkObjects.Count; i++)
            {
                if (!networkObjects[i].IsSpawned)
                {
                    throw new SpawnStateException("Object is not spawned");
                }

                if (!networkObjects[i].m_Observers.Contains(clientId))
                {
                    throw new VisibilityChangeException($"{nameof(NetworkObject)} with {nameof(NetworkObjectId)}: {networkObjects[i].NetworkObjectId} is already hidden");
                }
            }

            using (var buffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(buffer))
                {
                    writer.WriteUInt16Packed((ushort)networkObjects.Count);

                    for (int i = 0; i < networkObjects.Count; i++)
                    {
                        // Send destroy call
                        networkObjects[i].m_Observers.Remove(clientId);

                        writer.WriteUInt64Packed(networkObjects[i].NetworkObjectId);
                    }

                    InternalMessageSender.Send(clientId, NetworkConstants.DESTROY_OBJECTS, NetworkChannel.Internal, buffer);
                }
        }
Ejemplo n.º 14
0
        public void ShrinkCapacity()
        {
            NetworkWriterPool.Capacity = 2;

            // get writer and recycle so we have 2 in there, hence 'next' is at limit
            PooledNetworkWriter a = NetworkWriterPool.GetWriter();
            PooledNetworkWriter b = NetworkWriterPool.GetWriter();

            NetworkWriterPool.Recycle(a);
            NetworkWriterPool.Recycle(b);

            // shrink
            NetworkWriterPool.Capacity = 1;

            // get one. should return the only one which is still in there.
            PooledNetworkWriter c = NetworkWriterPool.GetWriter();

            Assert.That(c, !Is.Null);
            Assert.That(c == a || c == b);
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Send fake values to client's <see cref="Mirror.ClientRpcAttribute"/>.
        /// </summary>
        /// <param name="target">Target to send.</param>
        /// <param name="behaviorOwner"><see cref="Mirror.NetworkIdentity"/> of object that owns <see cref="Mirror.NetworkBehaviour"/>.</param>
        /// <param name="targetType"><see cref="Mirror.NetworkBehaviour"/>'s type.</param>
        /// <param name="rpcName">Property name starting with Rpc.</param>
        /// <param name="values">Values of send to target.</param>
        public static void SendFakeTargetRpc(Player target, NetworkIdentity behaviorOwner, Type targetType, string rpcName, params object[] values)
        {
            PooledNetworkWriter writer = NetworkWriterPool.GetWriter();

            foreach (object value in values)
            {
                WriterExtensions[value.GetType()].Invoke(null, new object[] { writer, value });
            }

            RpcMessage msg = new RpcMessage
            {
                netId          = behaviorOwner.netId,
                componentIndex = GetComponentIndex(behaviorOwner, targetType),
                functionHash   = (targetType.FullName.GetStableHashCode() * 503) + rpcName.GetStableHashCode(),
                payload        = writer.ToArraySegment(),
            };

            target.Connection.Send(msg, 0);
            NetworkWriterPool.Recycle(writer);
        }
Ejemplo n.º 16
0
        public void StartGame()
        {
            var pts = new HashSet <Transform>(_SpawnPoints.GetComponentsInChildren <Transform>());

            pts.Remove(_SpawnPoints.transform); // Why does unity return parent also ?

            foreach (var(player, point) in _SessionManager.Zip(pts, (player, point) => (player, point.localPosition)))
            {
                var obj = Instantiate(_PlayerPrefab, point, Quaternion.identity);

                using var stream = PooledNetworkBuffer.Get();
                using var writer = PooledNetworkWriter.Get(stream);

                writer.WriteByte((byte)player.Character);
                writer.WritePadBits();

                var net = obj.GetComponent <NetworkObject>();

                net.SpawnAsPlayerObject(player.ID, stream, true);
            }
        }
        /// <summary>
        /// Sends the named message
        /// </summary>
        /// <param name="name">The message name to send</param>
        /// <param name="clientIds">The clients to send to, sends to everyone if null</param>
        /// <param name="stream">The message stream containing the data</param>
        /// <param name="networkChannel">The channel to send the data on</param>
        public static void SendNamedMessage(string name, List <ulong> clientIds, Stream stream, NetworkChannel networkChannel = NetworkChannel.Internal)
        {
            ulong hash = 0;

            switch (NetworkManager.Singleton.NetworkConfig.RpcHashSize)
            {
            case HashSize.VarIntTwoBytes:
                hash = name.GetStableHash16();
                break;

            case HashSize.VarIntFourBytes:
                hash = name.GetStableHash32();
                break;

            case HashSize.VarIntEightBytes:
                hash = name.GetStableHash64();
                break;
            }

            using (var messageBuffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(messageBuffer))
                {
                    writer.WriteUInt64Packed(hash);

                    messageBuffer.CopyFrom(stream);

                    if (!NetworkManager.Singleton.IsServer)
                    {
                        if (NetworkLog.CurrentLogLevel <= LogLevel.Error)
                        {
                            NetworkLog.LogWarning("Can not send named messages to multiple users as a client");
                        }
                        return;
                    }

                    InternalMessageSender.Send(NetworkConstants.NAMED_MESSAGE, networkChannel, clientIds, messageBuffer);
                    PerformanceDataManager.Increment(ProfilerConstants.NamedMessageSent);
                }
        }
Ejemplo n.º 18
0
        public void BufferReturnsMutliplePacketsInTheOrderTheyWereWriten()
        {
            const string expectedMessage1 = "first Message";
            const string expectedMessage2 = "second Message";

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                writer.WriteString(expectedMessage1);

                buffer.Write(writer.ToArraySegment());
            }

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                writer.WriteString(expectedMessage2);

                buffer.Write(writer.ToArraySegment());
            }

            string message1;
            string message2;
            ArraySegment <byte> package1 = buffer.GetNextPacket();

            using (PooledNetworkReader reader = NetworkReaderPool.GetReader(package1))
            {
                message1 = reader.ReadString();
            }

            Assert.IsTrue(buffer.HasPackets());
            ArraySegment <byte> package2 = buffer.GetNextPacket();

            using (PooledNetworkReader reader = NetworkReaderPool.GetReader(package2))
            {
                message2 = reader.ReadString();
            }

            Assert.That(message1, Is.EqualTo(expectedMessage1));
            Assert.That(message2, Is.EqualTo(expectedMessage2));
        }
Ejemplo n.º 19
0
        public void SyncVarIsBitPacked([ValueSource(nameof(cases))] TestCase TestCase)
        {
            int value            = TestCase.value;
            int expectedBitCount = TestCase.expectedBits;

            serverComponent.myValue = value;

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                serverComponent.SerializeSyncVars(writer, true);

                Assert.That(writer.BitPosition, Is.EqualTo(expectedBitCount));

                using (PooledNetworkReader reader = NetworkReaderPool.GetReader(writer.ToArraySegment()))
                {
                    clientComponent.DeserializeSyncVars(reader, true);
                    Assert.That(reader.BitPosition, Is.EqualTo(expectedBitCount));

                    Assert.That(clientComponent.myValue, Is.EqualTo(value));
                }
            }
        }
Ejemplo n.º 20
0
        public void SendLargerMaxBatchSizedMessageBatch()
        {
            int maxBatch  = transport.GetMaxBatchSize(Channels.Reliable);
            int maxPacket = transport.GetMaxPacketSize(Channels.Reliable);

            // we can only tested if transport max batch < max message
            Assert.That(maxBatch < maxPacket, Is.True);

            // create a message > batch size
            byte[] message = new byte[maxPacket];

            // add to batch queue
            PooledNetworkWriter writer = NetworkWriterPool.GetWriter();

            writer.WriteBytes(message, 0, message.Length);
            batch.messages.Enqueue(writer);

            // send batch - client should receive that exact message
            connection.SendBatch(Channels.Reliable, batch);
            Assert.That(transport.clientIncoming.Count, Is.EqualTo(1));
            Assert.That(transport.clientIncoming.Dequeue().data.Length, Is.EqualTo(message.Length));
        }
Ejemplo n.º 21
0
        public IEnumerator SendMany()
        {
            Task <RunNode.Result> task = RunNode.RunAsync("ReceiveManyMessages.js", 5_000);

            yield return(server.WaitForConnection);

            const int messageCount = 100;

            for (int i = 0; i < messageCount; i++)
            {
                using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
                {
                    writer.WriteByte((byte)i);
                    writer.WriteInt32(100);

                    ArraySegment <byte> segment = writer.ToArraySegment();

                    server.ServerSend(new List <int> {
                        1
                    }, Channels.DefaultReliable, segment);
                }
            }

            yield return(new WaitForSeconds(1));

            server.ServerDisconnect(1);

            yield return(new WaitUntil(() => task.IsCompleted));

            RunNode.Result result = task.Result;

            string expectedFormat         = "length: 5 msg: {0:X2} 64 00 00 00";
            IEnumerable <string> expected = Enumerable.Range(0, messageCount).Select(i => string.Format(expectedFormat, i));

            result.AssetTimeout(false);
            result.AssetOutput(expected.ToArray());
            result.AssetErrors();
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Returns a base64 encoded version of the config
        /// </summary>
        /// <returns></returns>
        public string ToBase64()
        {
            NetworkConfig config = this;

            using (var buffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(buffer))
                {
                    writer.WriteUInt16Packed(config.ProtocolVersion);
                    writer.WriteUInt16Packed((ushort)config.RegisteredScenes.Count);

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

                    writer.WriteInt32Packed(config.ReceiveTickrate);
                    writer.WriteInt32Packed(config.MaxReceiveEventsPerTickRate);
                    writer.WriteInt32Packed(config.EventTickrate);
                    writer.WriteInt32Packed(config.ClientConnectionBufferTimeout);
                    writer.WriteBool(config.ConnectionApproval);
                    writer.WriteInt32Packed(config.SecondsHistory);
                    writer.WriteInt32Packed(config.LoadSceneTimeOut);
                    writer.WriteBool(config.EnableTimeResync);
                    writer.WriteBool(config.EnsureNetworkVariableLengthSafety);
                    writer.WriteBits((byte)config.RpcHashSize, 2);
                    writer.WriteBool(ForceSamePrefabs);
                    writer.WriteBool(UsePrefabSync);
                    writer.WriteBool(EnableSceneManagement);
                    writer.WriteBool(RecycleNetworkIds);
                    writer.WriteSinglePacked(NetworkIdRecycleDelay);
                    writer.WriteBool(EnableNetworkVariable);
                    writer.WriteBool(AllowRuntimeSceneChanges);
                    writer.WriteBool(EnableNetworkLogs);
                    buffer.PadBuffer();

                    return(Convert.ToBase64String(buffer.ToArray()));
                }
        }
Ejemplo n.º 23
0
        public void PoolReUsesWritersUpToSizeLimit()
        {
            NetworkWriterPool.Capacity = 1;

            // get 2 writers
            PooledNetworkWriter a = NetworkWriterPool.GetWriter();
            PooledNetworkWriter b = NetworkWriterPool.GetWriter();

            // recycle all
            NetworkWriterPool.Recycle(a);
            NetworkWriterPool.Recycle(b);

            // get 2 new ones
            PooledNetworkWriter c = NetworkWriterPool.GetWriter();
            PooledNetworkWriter d = NetworkWriterPool.GetWriter();

            // exactly one should be reused, one should be new
            bool cReused = c == a || c == b;
            bool dReused = d == a || d == b;

            Assert.That((cReused && !dReused) ||
                        (!cReused && dReused));
        }
Ejemplo n.º 24
0
        public void MessageIsBitPacked()
        {
            var inStruct = new BitPackStruct
            {
                myValue = value,
            };

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                // generic write, uses generated function that should include bitPacking
                writer.Write(inStruct);

                Assert.That(writer.BitPosition, Is.EqualTo(32));

                using (PooledNetworkReader reader = NetworkReaderPool.GetReader(writer.ToArraySegment(), null))
                {
                    var outStruct = reader.Read <BitPackStruct>();
                    Assert.That(reader.BitPosition, Is.EqualTo(32));

                    Assert.That(outStruct, Is.EqualTo(inStruct));
                }
            }
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Shows a list of previously hidden objects to a client
        /// </summary>
        /// <param name="networkObjects">The objects to show</param>
        /// <param name="clientId">The client to show the objects to</param>
        /// <param name="payload">An optional payload to send as part of the spawns</param>
        public static void NetworkShow(List <NetworkObject> networkObjects, ulong clientId, Stream payload = null)
        {
            if (!NetworkManager.Singleton.IsServer)
            {
                throw new NotServerException("Only server can change visibility");
            }

            // Do the safety loop first to prevent putting the MLAPI in an invalid state.
            for (int i = 0; i < networkObjects.Count; i++)
            {
                if (!networkObjects[i].IsSpawned)
                {
                    throw new SpawnStateException("Object is not spawned");
                }

                if (networkObjects[i].m_Observers.Contains(clientId))
                {
                    throw new VisibilityChangeException($"{nameof(NetworkObject)} with NetworkId: {networkObjects[i].NetworkObjectId} is already visible");
                }
            }

            using (var buffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(buffer))
                {
                    writer.WriteUInt16Packed((ushort)networkObjects.Count);

                    for (int i = 0; i < networkObjects.Count; i++)
                    {
                        // Send spawn call
                        networkObjects[i].m_Observers.Add(clientId);

                        NetworkSpawnManager.WriteSpawnCallForObject(buffer, clientId, networkObjects[i], payload);
                    }

                    InternalMessageSender.Send(clientId, NetworkConstants.ADD_OBJECTS, NetworkChannel.Internal, buffer);
                }
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Reply to the client to inform it of this server
        /// </summary>
        /// <remarks>
        /// Override if you wish to ignore server requests based on
        /// custom criteria such as language, full server game mode or difficulty
        /// </remarks>
        /// <param name="request">Request comming from client</param>
        /// <param name="endpoint">Address of the client that sent the request</param>
        protected virtual void ProcessClientRequest(Request request, IPEndPoint endpoint)
        {
            Response info = ProcessRequest(request, endpoint);

            if (info == null)
            {
                return;
            }

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter()) {
                try {
                    writer.WriteInt64(secretHandshake);

                    writer.Write(info);

                    ArraySegment <byte> data = writer.ToArraySegment();
                    // signature matches
                    // send response
                    serverUdpClient.Send(data.Array, data.Count, endpoint);
                } catch (Exception ex) {
                    Debug.LogException(ex, this);
                }
            }
        }
        internal void ChangeOwnership(NetworkObject networkObject, ulong clientId)
        {
            if (!NetworkManager.IsServer)
            {
                throw new NotServerException("Only the server can change ownership");
            }

            if (!networkObject.IsSpawned)
            {
                throw new SpawnStateException("Object is not spawned");
            }

            if (NetworkManager.ConnectedClients.TryGetValue(networkObject.OwnerClientId, out NetworkClient networkClient))
            {
                for (int i = networkClient.OwnedObjects.Count - 1; i >= 0; i--)
                {
                    if (networkClient.OwnedObjects[i] == networkObject)
                    {
                        networkClient.OwnedObjects.RemoveAt(i);
                    }
                }

                networkClient.OwnedObjects.Add(networkObject);
            }

            networkObject.OwnerClientId = clientId;

            using (var buffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(buffer))
                {
                    writer.WriteUInt64Packed(networkObject.NetworkObjectId);
                    writer.WriteUInt64Packed(clientId);

                    NetworkManager.MessageSender.Send(NetworkConstants.CHANGE_OWNER, NetworkChannel.Internal, buffer);
                }
        }
Ejemplo n.º 28
0
        internal static void OnDestroyObject(ulong networkId, bool destroyGameObject)
        {
            if (ReferenceEquals(NetworkManager.Singleton, null))
            {
                return;
            }

            //Removal of spawned object
            if (!SpawnedObjects.ContainsKey(networkId))
            {
                Debug.LogWarning($"Trying to destroy object {networkId} but it doesn't seem to exist anymore!");
                return;
            }

            var sobj = SpawnedObjects[networkId];

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

            sobj.IsSpawned = false;

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

                var rpcQueueContainer = NetworkManager.Singleton.RpcQueueContainer;
                if (rpcQueueContainer != null)
                {
                    if (!ReferenceEquals(sobj, null))
                    {
                        // As long as we have any remaining clients, then notify of the object being destroy.
                        if (NetworkManager.Singleton.ConnectedClientsList.Count > 0)
                        {
                            var buffer = PooledNetworkBuffer.Get();
                            using (var writer = PooledNetworkWriter.Get(buffer))
                            {
                                writer.WriteUInt64Packed(networkId);

                                var queueItem = new RpcFrameQueueItem
                                {
                                    UpdateStage      = NetworkUpdateStage.PostLateUpdate,
                                    QueueItemType    = RpcQueueContainer.QueueItemType.DestroyObject,
                                    NetworkId        = networkId,
                                    NetworkBuffer    = buffer,
                                    NetworkChannel   = NetworkChannel.Internal,
                                    ClientNetworkIds = NetworkManager.Singleton.ConnectedClientsList.Select(c => c.ClientId).ToArray()
                                };

                                rpcQueueContainer.AddToInternalMLAPISendQueue(queueItem);
                            }
                        }
                    }
                }
            }

            var gobj = sobj.gameObject;

            if (destroyGameObject && !ReferenceEquals(gobj, null))
            {
                if (CustomDestroyHandlers.ContainsKey(sobj.PrefabHash))
                {
                    CustomDestroyHandlers[sobj.PrefabHash](sobj);
                    OnDestroyObject(networkId, false);
                }
                else
                {
                    MonoBehaviour.Destroy(gobj);
                }
            }

            // for some reason, we can get down here and SpawnedObjects for this
            //  networkId will no longer be here, even as we check this at the start
            //  of the function
            if (SpawnedObjects.ContainsKey(networkId))
            {
                SpawnedObjectsList.Remove(sobj);
                SpawnedObjects.Remove(networkId);
            }
        }
Ejemplo n.º 29
0
        internal static void WriteSpawnCallForObject(Serialization.NetworkBuffer buffer, ulong clientId, NetworkObject networkObject, Stream payload)
        {
            using (var writer = PooledNetworkWriter.Get(buffer))
            {
                writer.WriteBool(networkObject.IsPlayerObject);
                writer.WriteUInt64Packed(networkObject.NetworkObjectId);
                writer.WriteUInt64Packed(networkObject.OwnerClientId);

                NetworkObject parentNetworkObject = null;

                if (!networkObject.AlwaysReplicateAsRoot && !ReferenceEquals(networkObject.transform.parent, null))
                {
                    parentNetworkObject = networkObject.transform.parent.GetComponent <NetworkObject>();
                }

                if (ReferenceEquals(parentNetworkObject, null))
                {
                    writer.WriteBool(false);
                }
                else
                {
                    writer.WriteBool(true);
                    writer.WriteUInt64Packed(parentNetworkObject.NetworkObjectId);
                }

                if (!NetworkManager.Singleton.NetworkConfig.EnableSceneManagement || NetworkManager.Singleton.NetworkConfig.UsePrefabSync)
                {
                    writer.WriteUInt64Packed(networkObject.PrefabHash);
                }
                else
                {
                    writer.WriteBool(networkObject.IsSceneObject ?? true);

                    if (networkObject.IsSceneObject == null || networkObject.IsSceneObject.Value)
                    {
                        writer.WriteUInt64Packed(networkObject.NetworkInstanceId);
                    }
                    else
                    {
                        writer.WriteUInt64Packed(networkObject.PrefabHash);
                    }
                }

                if (networkObject.IncludeTransformWhenSpawning == null || networkObject.IncludeTransformWhenSpawning(clientId))
                {
                    writer.WriteBool(true);
                    writer.WriteSinglePacked(networkObject.transform.position.x);
                    writer.WriteSinglePacked(networkObject.transform.position.y);
                    writer.WriteSinglePacked(networkObject.transform.position.z);

                    writer.WriteSinglePacked(networkObject.transform.rotation.eulerAngles.x);
                    writer.WriteSinglePacked(networkObject.transform.rotation.eulerAngles.y);
                    writer.WriteSinglePacked(networkObject.transform.rotation.eulerAngles.z);
                }
                else
                {
                    writer.WriteBool(false);
                }

                writer.WriteBool(payload != null);

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

                if (NetworkManager.Singleton.NetworkConfig.EnableNetworkVariable)
                {
                    networkObject.WriteNetworkVariableData(buffer, clientId);
                }

                if (payload != null)
                {
                    buffer.CopyFrom(payload);
                }
            }
        }
        private static void OnSceneUnloadClient(Guid switchSceneGuid, Stream objectStream)
        {
            if (!NetworkManager.Singleton.NetworkConfig.EnableSceneManagement || NetworkManager.Singleton.NetworkConfig.UsePrefabSync)
            {
                NetworkSpawnManager.DestroySceneObjects();

                using (var reader = PooledNetworkReader.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());
                        }

                        var networkObject = NetworkSpawnManager.CreateLocalNetworkObject(false, 0, prefabHash, parentNetworkId, position, rotation);
                        NetworkSpawnManager.SpawnNetworkObjectLocally(networkObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, false);

                        var bufferQueue = BufferManager.ConsumeBuffersForNetworkId(networkId);

                        // Apply buffered messages
                        if (bufferQueue != null)
                        {
                            while (bufferQueue.Count > 0)
                            {
                                BufferManager.BufferedMessage message = bufferQueue.Dequeue();
                                NetworkManager.Singleton.HandleIncomingData(message.SenderClientId, message.NetworkChannel, new ArraySegment <byte>(message.NetworkBuffer.GetBuffer(), (int)message.NetworkBuffer.Position, (int)message.NetworkBuffer.Length), message.ReceiveTime, false);
                                BufferManager.RecycleConsumedBufferedMessage(message);
                            }
                        }
                    }
                }
            }
            else
            {
                var networkObjects = MonoBehaviour.FindObjectsOfType <NetworkObject>();
                NetworkSpawnManager.ClientCollectSoftSyncSceneObjectSweep(networkObjects);

                using (var reader = PooledNetworkReader.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();

                        var networkObject = NetworkSpawnManager.CreateLocalNetworkObject(true, instanceId, 0, parentNetworkId, null, null);
                        NetworkSpawnManager.SpawnNetworkObjectLocally(networkObject, networkId, true, isPlayerObject, owner, objectStream, false, 0, true, false);

                        var bufferQueue = BufferManager.ConsumeBuffersForNetworkId(networkId);

                        // Apply buffered messages
                        if (bufferQueue != null)
                        {
                            while (bufferQueue.Count > 0)
                            {
                                BufferManager.BufferedMessage message = bufferQueue.Dequeue();
                                NetworkManager.Singleton.HandleIncomingData(message.SenderClientId, message.NetworkChannel, new ArraySegment <byte>(message.NetworkBuffer.GetBuffer(), (int)message.NetworkBuffer.Position, (int)message.NetworkBuffer.Length), message.ReceiveTime, false);
                                BufferManager.RecycleConsumedBufferedMessage(message);
                            }
                        }
                    }
                }
            }

            using (var buffer = PooledNetworkBuffer.Get())
                using (var writer = PooledNetworkWriter.Get(buffer))
                {
                    writer.WriteByteArray(switchSceneGuid.ToByteArray());
                    InternalMessageSender.Send(NetworkManager.Singleton.ServerClientId, NetworkConstants.CLIENT_SWITCH_SCENE_COMPLETED, NetworkChannel.Internal, buffer);
                }

            s_IsSwitching = false;

            OnSceneSwitched?.Invoke();
        }