Beispiel #1
0
        public void SyncVarIsBitPacked([ValueSource(nameof(cases))] TestCase TestCase)
        {
            MyEnumByte 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(), null))
                {
                    clientComponent.DeserializeSyncVars(reader, true);
                    Assert.That(reader.BitPosition, Is.EqualTo(expectedBitCount));

                    Assert.That(clientComponent.myValue, Is.EqualTo(value));
                }
            }
        }
        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));
        }
Beispiel #3
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));
        }
Beispiel #4
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();
        }
Beispiel #5
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));
                }
            }
        }
Beispiel #6
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));
        }
        protected virtual void Update()
        {
            if (!hasAuthority)
            {
                return;
            }

            if (NetworkTime.localTime >= _lastSendTime + SendInterval)
            {
                _lastSendTime = NetworkTime.localTime;

                if (!HasChanged())
                {
                    return;
                }

                using var writer = NetworkWriterPool.GetWriter();
                Serialize(writer);
                UpdatePrevData();

                var data = writer.ToArraySegment();
                if (UseReliableRpc)
                {
                    CmdSendDataReliable(data);
                }
                else
                {
                    CmdSendDataUnreliable(data);
                }

                if (QSBCore.IsHost)
                {
                    _lastKnownData ??= new byte[data.Count];
                    Array.Copy(data.Array !, data.Offset, _lastKnownData, 0, data.Count);
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Send custom values to client's SyncObject.
        /// </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="customAction">Custom writing action.</param>
        public static void SendCustomSyncObject(this Player target, NetworkIdentity behaviorOwner, Type targetType, Action <NetworkWriter> customAction)
        {
            /*
             * Cant be use if you dont understand(ill make more use easily soonTM)
             * Example(SyncList) [EffectOnlySCP207]:
             * player.SendCustomSync(player.ReferenceHub.networkIdentity, typeof(PlayerEffectsController), (writer) => {
             *      writer.WritePackedUInt64(1ul);								// DirtyObjectsBit
             *      writer.WritePackedUInt32((uint)1);							// DirtyIndexCount
             *      writer.WriteByte((byte)SyncList<byte>.Operation.OP_SET);	// Operations
             *      writer.WritePackedUInt32((uint)0);							// EditIndex
             *      writer.WriteByte((byte)1);									// Item
             * });
             */
            NetworkWriter writer  = NetworkWriterPool.GetWriter();
            NetworkWriter writer2 = NetworkWriterPool.GetWriter();

            MakeCustomSyncWriter(behaviorOwner, targetType, customAction, null, writer, writer2);
            NetworkServer.SendToClientOfPlayer(target.ReferenceHub.networkIdentity, new UpdateVarsMessage()
            {
                netId = behaviorOwner.netId, payload = writer.ToArraySegment()
            });
            NetworkWriterPool.Recycle(writer);
            NetworkWriterPool.Recycle(writer2);
        }
        /// <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);
                }
            }
        }
Beispiel #10
0
        /// <summary>
        /// Replaces the user code with a stub.
        /// Moves the original code to a new method
        /// </summary>
        /// <param name="td">The class containing the method </param>
        /// <param name="md">The method to be stubbed </param>
        /// <param name="ServerRpcAttr">The attribute that made this an RPC</param>
        /// <returns>The method containing the original code</returns>
        /// <remarks>
        /// Generates code like this:
        /// <code>
        /// public void MyServerRpc(float thrusting, int spin)
        /// {
        ///     NetworkWriter networkWriter = new NetworkWriter();
        ///     networkWriter.Write(thrusting);
        ///     networkWriter.WritePackedUInt32((uint) spin);
        ///     base.SendServerRpcInternal(cmdName, networkWriter, cmdName);
        /// }
        ///
        /// public void UserCode_MyServerRpc(float thrusting, int spin)
        /// {
        ///     // whatever the user was doing before
        ///
        /// }
        /// </code>
        /// </remarks>
        MethodDefinition GenerateStub(MethodDefinition md, CustomAttribute serverRpcAttr)
        {
            MethodDefinition cmd = SubstituteMethod(md);

            ILProcessor worker = md.Body.GetILProcessor();

            // if (IsServer)
            // {
            //    call the body
            //    return;
            // }
            CallBody(worker, cmd);

            // NetworkWriter writer = NetworkWriterPool.GetWriter()
            VariableDefinition writer = md.AddLocal <PooledNetworkWriter>();

            worker.Append(worker.Create(OpCodes.Call, md.Module.ImportReference(() => NetworkWriterPool.GetWriter())));
            worker.Append(worker.Create(OpCodes.Stloc, writer));

            // write all the arguments that the user passed to the Cmd call
            if (!WriteArguments(worker, md, writer, RemoteCallType.ServerRpc))
            {
                return(cmd);
            }

            string cmdName = md.Name;

            int  channel          = serverRpcAttr.GetField("channel", 0);
            bool requireAuthority = serverRpcAttr.GetField("requireAuthority", true);


            // invoke internal send and return
            // load 'base.' to call the SendServerRpc function with
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldtoken, md.DeclaringType.ConvertToGenericIfNeeded()));
            // invokerClass
            worker.Append(worker.Create(OpCodes.Call, () => Type.GetTypeFromHandle(default)));
Beispiel #11
0
        /// <summary>
        /// Replaces the user code with a stub.
        /// Moves the original code to a new method
        /// </summary>
        /// <param name="td">The class containing the method </param>
        /// <param name="md">The method to be stubbed </param>
        /// <param name="ServerRpcAttr">The attribute that made this an RPC</param>
        /// <returns>The method containing the original code</returns>
        /// <remarks>
        /// Generates code like this:
        /// <code>
        /// public void MyServerRpc(float thrusting, int spin)
        /// {
        ///     NetworkWriter networkWriter = new NetworkWriter();
        ///     networkWriter.Write(thrusting);
        ///     networkWriter.WritePackedUInt32((uint) spin);
        ///     base.SendServerRpcInternal(cmdName, networkWriter, cmdName);
        /// }
        ///
        /// public void UserCode_MyServerRpc(float thrusting, int spin)
        /// {
        ///     // whatever the user was doing before
        ///
        /// }
        /// </code>
        /// </remarks>
        private MethodDefinition GenerateStub(MethodDefinition md, CustomAttribute serverRpcAttr, int rpcIndex, ValueSerializer[] paramSerializers)
        {
            var cmd = SubstituteMethod(md);

            var worker = md.Body.GetILProcessor();

            // if (IsServer)
            // {
            //    call the body
            //    return;
            // }
            CallBody(worker, cmd);

            // NetworkWriter writer = NetworkWriterPool.GetWriter()
            var writer = md.AddLocal <PooledNetworkWriter>();

            worker.Append(worker.Create(OpCodes.Call, md.Module.ImportReference(() => NetworkWriterPool.GetWriter())));
            worker.Append(worker.Create(OpCodes.Stloc, writer));

            // write all the arguments that the user passed to the Cmd call
            WriteArguments(worker, md, writer, paramSerializers, RemoteCallType.ServerRpc);

            var cmdName = md.FullName;

            var channel          = serverRpcAttr.GetField(nameof(ServerRpcAttribute.channel), 0);
            var requireAuthority = serverRpcAttr.GetField(nameof(ServerRpcAttribute.requireAuthority), true);

            var sendMethod = GetSendMethod(md, worker);

            // ServerRpcSender.Send(this, 12345, writer, channel, requireAuthority)
            worker.Append(worker.Create(OpCodes.Ldarg_0));
            worker.Append(worker.Create(OpCodes.Ldc_I4, rpcIndex));
            worker.Append(worker.Create(OpCodes.Ldloc, writer));
            worker.Append(worker.Create(OpCodes.Ldc_I4, channel));
            worker.Append(worker.Create(requireAuthority ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0));
            worker.Append(worker.Create(OpCodes.Call, sendMethod));

            NetworkWriterHelper.CallRelease(module, worker, writer);

            worker.Append(worker.Create(OpCodes.Ret));

            return(cmd);
        }