Exemple #1
0
	bool CheckRelevancy(Actor actor, out ObjectReplicator repl, out bool isRelevant) {
		Perf.Begin("CheckRelevancy");
		isRelevant = actor.IsNetRelevantFor(this);

		repl = actor.internal_GetReplicator(connection);
		if (repl != null) {
			if (repl.wasRelevant != isRelevant) {
				Perf.End();
				return true;
			}
		}

		Perf.End();
		return isRelevant;
	}
Exemple #2
0
	public void Ping(float dt) {
		Perf.Begin("Ping");
		nextPingTime -= dt;
		if (nextPingTime <= 0f) {
			nextPingTime = PING_RATE;
#if UNITY_EDITOR && !PROFILING
			pongTimeout = Mathf.Max(pongTimeout, maxPongTimeout);
#else
			connection.SendReliable(NetMsgs.Ping.New(Utils.ReadMilliseconds()));
#endif
		}

		pongTimeout -= Mathf.Min(dt, 1/3f);
		Perf.End();
	}
    protected virtual void FixedUpdateActors(float dt)
    {
        Perf.Begin("World.FixedUpdate");

        for (int i = 0; i < _actors.Count; ++i)
        {
            var actor = _actors[i];

            if (!actor.pendingKill)
            {
                actor.FixedUpdate(dt);
            }
        }

        Perf.End();
    }
    public void SendReliable(byte[] buffer, int numBytes)
    {
        Perf.Begin("SocketNetDriverConnection.SendReliable");

        Assert.IsTrue(numBytes <= ushort.MaxValue);

        msgTemp[0] = (byte)(numBytes & 0xff);
        msgTemp[1] = (byte)((numBytes >> 8) & 0xff);
        try {
            Array.Copy(buffer, 0, msgTemp, 2, numBytes);

            numBytes += 2;

            int numTries = 0;
            int numSent  = 0;

            do
            {
                var bytesSent = sockets[0].Send(msgTemp, numSent, numBytes - numSent, SocketFlags.None);
                numSent += bytesSent;
            } while ((numSent < numBytes) && (++numTries < 15));

            if (numSent != numBytes)
            {
                throw new Exception("Reliable socket send did not send all bytes (tried to send " + numBytes + " byte(s) but only sent " + numSent + ".");
            }

            ++reliableMetrics.numPacketsSent;
            reliableMetrics.bytesSent += numBytes;
        } catch (Exception e) {
            Debug.LogException(e);

            var socketException = e as SocketException;
            if (socketException != null)
            {
                if (socketException.SocketErrorCode == SocketError.WouldBlock)
                {
                    _driver.ReliableSendWouldBlock(this);
                    return;
                }
            }

            Dispose();
        }

        Perf.End();
    }
    public void TickClient(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics)
    {
        Perf.Begin("SocketNetDriver.TickClient");

        if (_serverConnection != null)
        {
            bool wasReset   = false;
            bool isDisposed = false;

            try {
                wasReset = _serverConnection.sockets[0].Poll(0, SelectMode.SelectRead);
            } catch (Exception) {
                isDisposed = true;
            }

            if (isDisposed || (wasReset && (_serverConnection.sockets[0].Available == 0)))
            {
                Debug.LogError("Server connection was reset.");
                _serverConnection.Dispose();
                // don't set _serverConnection to null so NetDriverConnection's can be cleaned up correctly.
                Perf.End();
                return;
            }

            Recv(_serverConnection, _clientCallbacks, _serverConnection.sockets[0], recvBuffer, ref reliableChannelMetrics, false);

            if (_serverConnection != null)
            {
                Recv(_serverConnection, _clientCallbacks, _serverConnection.sockets[1], recvBuffer, ref unreliableChannelMetrics, true);
            }

            if (_serverConnection != null)
            {
                if (!_serverConnection.didHandshake && (_serverConnection.channelID != -1))
                {
                    _sendUdpControlTimeout -= dt;
                    if (_sendUdpControlTimeout <= 0f)
                    {
                        _sendUdpControlTimeout = UDP_CONTROL_RESEND_TIMEOUT;
                        SendUdpControl(_serverConnection);
                    }
                }
            }
        }

        Perf.End();
    }
Exemple #6
0
        public void NewickFileTest()
        {
            // parse
            Perf.Start("Parsing...");
            string filepath = @"TestData\PhylogeneticTree\tree.txt";

            NewickParser parser           = new NewickParser();
            Tree         phylogeneticTree = parser.Parse(filepath);

            Perf.End();

            string outpath = @"TestData\PhylogeneticTree\out.txt";

            Perf.Start("Formatting...");
            NewickFormatter formatter = new NewickFormatter();

            formatter.Format(phylogeneticTree, outpath);
            Perf.End();
            Assert.AreEqual(true, FileCompare(filepath, outpath));
        }
Exemple #7
0
        public void NewickStringTest()
        {
            StringBuilder input = new StringBuilder("(A:0.1,B:0.2,(C:0.3,D:0.4):0.5);");

            // parse
            Perf.Start("Parsing...");
            using (NewickParser parser = new NewickParser())
            {
                Tree phylogeneticTree = parser.Parse(input);

                Perf.End();

                Perf.Start("Formatting...");
                NewickFormatter formatter = new NewickFormatter();

                string output = formatter.FormatString(phylogeneticTree);
                Perf.End();
                Assert.AreEqual(input.ToString(), output);
            }
        }
    public void SendUnreliable(byte[] buffer, int numBytes)
    {
        Perf.Begin("SocketNetDriverConnection.SendUnreliable");

        try {
            var numSent = sockets[1].SendTo(buffer, 0, numBytes, SocketFlags.None, udpEndpoint);
            if (numSent != numBytes)
            {
                Debug.LogError("Unreliable socket send did not send all bytes (tried to send " + numBytes + " byte(s) but only sent " + numSent + ".");
                throw new SocketException((int)SocketError.SocketError);
            }
            ++unreliableMetrics.numPacketsSent;
            unreliableMetrics.bytesSent += numBytes;
        } catch (Exception e) {
            Debug.LogError("Unreliable socket send failed with exception (tried to send " + numBytes + " byte(s).");
            Debug.LogException(e);
            Dispose();
        }

        Perf.End();
    }
Exemple #9
0
    void RecvMessages(byte[] src, int srcLen, byte[] dst, LocalGameNetDriverConnection conn, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics)
    {
        Perf.Begin("LocalGameNetDriver.RecvMessages");

        for (int i = 0; i < srcLen - 4;)
        {
            if (!conn.isValid)
            {
                break;
            }

            int msgLen = System.BitConverter.ToInt32(src, i);
            i += 4;

            Assert.IsTrue(msgLen > 0);

            if (msgLen > 0)
            {
                System.Array.Copy(src, i, dst, 0, msgLen);
                try {
                    Perf.Begin("LocalGameNetDriver.RecvMessages.Callbacks.OnMessageReceived");
                    conn.callbacks.OnMessageReceived(conn, dst, msgLen);
                    Perf.End();
                } catch (System.Exception e) {
                    Debug.LogException(e);
                }
            }
            else
            {
                conn.callbacks.OnInvalidMessageReceived(conn);
            }

            i += msgLen;             // increment before callback in-case there is an exception

            reliableChannelMetrics.bytesRecv += msgLen;
            ++reliableChannelMetrics.numPacketsRecv;
        }

        Perf.End();
    }
Exemple #10
0
        public void ConsoleTest()
        {
            lock (mutex)
            {
                Perf.ClearHandlers();
                Perf.UseVerboseConsole();
                Perf.UseUdpClient("127.0.0.1", 26778);

                using (ConsoleAgent.Begin())
                {
                    Perf.Set();
                    Thread.Sleep(1);
                    Perf.Set("P2");
                    Thread.Sleep(1);
                    Perf.End();

                    var output = ConsoleAgent.ReadAllText();

                    Assert.True(output.IsMatch(new Regex(@"PerfProbe at  \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}  \(Thread: \d+\)
  File    : .+?PerfProbe.Test\\UnitTest1.cs
  Title   : \(null\)
  Lines   : \d+ ~ \d+
  Caller  : ConsoleTest
  Elapsed : \d{2}:\d{2}:\d{2}\.\d{7}
  Under   : .*?

PerfProbe at  \d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}  \(Thread: \d+\)
  File    : .+?PerfProbe.Test\\UnitTest1.cs
  Title   : P2
  Lines   : \d+ ~ \d+
  Caller  : ConsoleTest
  Elapsed : \d{2}:\d{2}:\d{2}.\d{7}
  Under   : .*?

")));
                }
            }
        }
Exemple #11
0
        public void ConsoleTest2()
        {
            lock (mutex)
            {
                Perf.ClearHandlers();
                Perf.UseConsole();
                Perf.UseUdpClient("127.0.0.1", 26778);

                using (ConsoleAgent.Begin())
                {
                    Perf.Set();
                    Thread.Sleep(1);
                    Perf.Set("P2");
                    Thread.Sleep(1);
                    Perf.End();

                    var output = ConsoleAgent.ReadAllText();

                    Assert.True(output.IsMatch(new Regex(@"\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} #\d+ UnitTest1.cs \( \d+ ~ \d+ \) \d{2}:\d{2}:\d{2}\.\d{7}
\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2} #\d+ UnitTest1.cs \( P2 \) \d{2}:\d{2}:\d{2}.\d{7}
")));
                }
            }
        }
    protected virtual void LateTickActors()
    {
        Perf.Begin("World.LateTickActors");
        for (int i = 0; i < _actors.Count;)
        {
            var actor = _actors[i];

            if (!actor.pendingKill)
            {
                actor.LateTick();
            }

            if (actor.pendingKill)
            {
                DestroyActor(actor, false);
                _actors.RemoveAt(i);
            }
            else
            {
                ++i;
            }
        }
        Perf.End();
    }
Exemple #13
0
	bool SerializeFields(float dt, NetArchive archive, bool deltasOnly, bool netFlush) {
		Perf.Begin("SerializeFields");

		ActorReplicationChannel.CHECK_FLD(archive);

		isLoading = archive.isLoading;
		if (isLoading) {
			byte numBits = archive.ReadByte();
			Assert.IsTrue(numBits <= SerializedObjectFields.MAX_REPLICATED_FIELDS);
			uint fieldBits = archive.ReadUnsignedBits(numBits);

			ActorReplicationChannel.CHECK_FLD(archive);

			for (int i = 0; i < numBits; ++i) {
				if (((1U << i) & fieldBits) != 0) {
					var fieldState = fieldStates.Values[i];
					
					curFieldState = fieldState;
					object obj = fieldState.fieldSpec.field.GetValue(_object);
					object orig = obj;

					ActorReplicationChannel.CHECK_FLD(archive);

					if (fieldState.fieldSpec.serializer.Serialize(archive, this, ref obj, null)) {
						fieldState.needsRep = fieldState.fieldSpec.onRep != null;

						if (fieldState.needsRep) {
							++numOnReps;
						}
					}

					ActorReplicationChannel.CHECK_FLD(archive);

					if (obj != orig) {
						fieldState.fieldSpec.field.SetValue(_object, obj);
					}
				}
			}

			curFieldState = null;
			Perf.End();
			return numBits > 0;
		} else {

			fieldsToReplicate.Clear();

			byte numBitsWritten = 0;
			uint fieldBits = 0;

			for (int i = 0; i < fieldStates.Values.Count; ++i) {
				var field = fieldStates.Values[i];

				object fieldVal;
				bool deltaField;

				if (field.IsDirty(channel, _object, dt, deltasOnly, hasReplicated, isOwner, netFlush, out fieldVal, out deltaField)) {
					numBitsWritten = (byte)(i + 1);
					fieldBits |= 1U << i;
					fieldsToReplicate.Add(new FieldReplicateInfo(i, fieldVal, deltaField));
				}
			}

			Assert.IsTrue(numBitsWritten <= SerializedObjectFields.MAX_REPLICATED_FIELDS);
			archive.Write(numBitsWritten);
			archive.WriteUnsignedBits(fieldBits, numBitsWritten);

			ActorReplicationChannel.CHECK_FLD(archive);

			for (int i = 0; i < fieldsToReplicate.Count; ++i) {
				var info = fieldsToReplicate[i];
				var field = fieldStates.Values[info.index];
				ActorReplicationChannel.CHECK_FLD(archive);
				field.Write(archive, this, info.fieldVal, info.deltaField);
				ActorReplicationChannel.CHECK_FLD(archive);
			}

			fieldsToReplicate.Clear();

			hasReplicated = true;

			Perf.End();
			return numBitsWritten > 0;
		}
	}
Exemple #14
0
	public void ReplicateActors(float dt) {
		if (!didHandshake) {
			handshakeTime += Mathf.Min(dt, 1/3f);
			// client hasn't finished connecting
			return;
		}

		Ping(dt);

		if (!clientLevelLoaded) {
			ResetTimeoutForTravel();
			return;
		}

		Perf.Begin("ActorReplicationChannel.ReplicateActors");

		isSending = true;
		objectRefs.Clear();

		var packet = NetMsgs.ReplicatedObjectData.New();

		for (int i = 0; i < connection.world.numReplicatedActors; ++i) {
			var actor = connection.world.GetReplicatedActor(i);
			Assert.IsFalse(actor.disposed);

			var isOwner = actor.ownerConnectionID == _connection.id;
			if (!isOwner && actor.ownerOnly) {
				// actor is not replicated on this channel.
				continue;
			}

			Assert.IsFalse(actor.netTornOff);

			bool isRelevant;
			ObjectReplicator replicator;

			if (!CheckRelevancy(actor, out replicator, out isRelevant)) {
				Assert.IsFalse(actor.internal_NetTearOff);
				continue;
			}

			ReplicateObject(dt, actor, actor, replicator, actor.ownerConnectionID == _connection.id, isRelevant, ref packet);
#if !PACKET_COMBINE
			packet = packet.Flush(connection);
#endif
			objectRefs.Remove(actor.netIDHashCode);
		}

		ReplicateDependencies(ref packet);
		packet.Flush(connection);

		if (isTraveling) {
			ResetTimeoutForTravel();
			isTraveling = false;
			GarbageCollect();
			connection.SendReliable(NetMsgs.ServerFinishedTravel.New());
			connection.driverConnection.blocking = false;
		}

		Perf.End();
	}
    public void TickServer(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics)
    {
        Perf.Begin("SocketNetDriver.TickServer");

        for (;;)
        {
            Socket newSocket;
            try {
                newSocket = _serverSock[0].Accept();
            } catch (SocketException) {
                break;
            }

            if (_tcpConnections.ContainsKey(newSocket.RemoteEndPoint))
            {
                Debug.LogError("Connection attempt from already connected client!");
                newSocket.Close();
                continue;
            }

            var clientSocks = new Socket[2];
            clientSocks[0] = newSocket;
            clientSocks[1] = _serverSock[1];

            newSocket.Blocking = false;
            //newSocket.NoDelay = true;
            newSocket.SendBufferSize = World.MAX_RELIABLE_MESSAGE_SIZE * 8;
            newSocket.SendTimeout    = 500;

            var newConn = new SocketNetDriverConnection(this, clientSocks, nextChannelID++);
            _tcpConnections.Add(newSocket.RemoteEndPoint, newConn);
            SendTcpControl(newConn);
        }

        for (int i = 0; i < _tcpConnections.Values.Count;)
        {
            var c = _tcpConnections.Values[i];

            bool wasReset   = false;
            bool isDisposed = false;

            try {
                wasReset = c.sockets[0].Poll(0, SelectMode.SelectRead);
            } catch (Exception) {
                isDisposed = true;
            }

            if (isDisposed || (wasReset && (c.sockets[0].Available == 0)))
            {
                c.Dispose();
                continue;
            }

            Recv(c, _serverCallbacks, c.sockets[0], recvBuffer, ref reliableChannelMetrics, false);

            if (c.isValid && !c.didHandshake)
            {
                c.handshakeTime += dt;
                if (c.handshakeTime > UDP_CONTROL_DISCONNECT_TIMEOUT)
                {
                    // handshake failed
                    Debug.LogError("Disconnecting " + c.tcpEndpoint.ToString() + ": udp handshake timed out");
                    c.Dispose();
                }
            }

            if (c.isValid)
            {
                ++i;
            }
        }

        RecvFrom(_serverCallbacks, _serverSock[1], recvBuffer, ref unreliableChannelMetrics);

        Perf.End();
    }
    void Recv(SocketNetDriverConnection connection, INetDriverCallbacks callbacks, Socket socket, byte[] buffer, ref NetIOMetrics metrics, bool isDatagram)
    {
        Perf.Begin("SocketNetDriver.Recv");

        if (isDatagram)
        {
            while (connection.isValid && (socket.Available > 0))
            {
                int r;
                try {
                    r = socket.Receive(buffer, 0, World.MAX_UNRELIABLE_MESSAGE_SIZE, SocketFlags.None);
                    if (r <= 0)
                    {
                        throw new SocketException((int)SocketError.SocketError);
                    }
                    metrics.bytesRecv += r;
                    ++metrics.numPacketsRecv;
                } catch (Exception e) {
                    Debug.LogException(e);
                    callbacks.OnInvalidMessageReceived(connection);
                    continue;
                }

                if (!connection.didHandshake)
                {
                    // client may receive a UDP packet before receiving control ACK
                    // so discard the packet until we process the ACK.
                    continue;
                }

                callbacks.OnMessageReceived(connection, buffer, r);
            }
        }
        else
        {
            while (connection.isValid && (socket.Available > 0))
            {
                if (connection.pendingRecvSize <= 0)
                {
                    if (socket.Available < 2)
                    {
                        break;
                    }

                    // read from socket.
                    if (socket.Receive(connection.pendingBytes, 0, 2, SocketFlags.None) != 2)
                    {
                        throw new SocketException((int)SocketError.SocketError);
                    }

                    connection.pendingRecvSize      = ((int)connection.pendingBytes[0]) | (((int)connection.pendingBytes[1]) << 8);
                    connection.pendingBytesReceived = 0;

                    if (connection.pendingRecvSize > connection.pendingBytes.Length)
                    {
                        callbacks.OnInvalidMessageReceived(connection);
                        continue;
                    }
                }

                {
                    // read from socket.
                    var numBytesToRead = Mathf.Min(socket.Available, connection.pendingRecvSize - connection.pendingBytesReceived);
                    if (numBytesToRead > 0)
                    {
                        if (socket.Receive(connection.pendingBytes, connection.pendingBytesReceived, numBytesToRead, SocketFlags.None) != numBytesToRead)
                        {
                            throw new SocketException((int)SocketError.SocketError);
                        }
                        connection.pendingBytesReceived += numBytesToRead;
                    }
                }

                Assert.IsTrue(connection.pendingBytesReceived <= connection.pendingRecvSize);

                if (connection.pendingBytesReceived >= connection.pendingRecvSize)
                {
                    if (!connection.didHandshake)
                    {
                        if (callbacks == _clientCallbacks)
                        {
                            if (connection.channelID == -1)
                            {
                                var id = RecvControl(connection.pendingBytes, connection.pendingRecvSize);
                                if (id == -1)
                                {
                                    connection.Dispose();
                                    break;
                                }
                                connection.channelID   = id;
                                _sendUdpControlTimeout = UDP_CONTROL_RESEND_TIMEOUT;
                                SendUdpControl(connection);
                            }
                            else if (connection.pendingBytes[0] == (byte)EControlCode.AckChannelID)
                            {
                                connection.didHandshake = true;
                                callbacks.OnConnect(connection);
                            }
                            else
                            {
                                // invalid response
                                connection.Dispose();
                                break;
                            }
                        }
                        else
                        {
                            connection.Dispose();
                            break;
                        }

                        connection.pendingRecvSize      = 0;
                        connection.pendingBytesReceived = 0;
                        continue;
                    }

                    Array.Copy(connection.pendingBytes, buffer, connection.pendingRecvSize);

                    var r = connection.pendingRecvSize;

                    connection.pendingBytesReceived = 0;
                    connection.pendingRecvSize      = 0;

                    metrics.bytesRecv += r;
                    ++metrics.numPacketsRecv;

                    callbacks.OnMessageReceived(connection, buffer, r);
                    continue;
                }

                // not enough data ready
                break;
            }
        }

        Perf.End();
    }
    void RecvFrom(INetDriverCallbacks callbacks, Socket socket, byte[] buffer, ref NetIOMetrics metrics)
    {
        Perf.Begin("SocketNetDriver.RecvFrom");

        while (socket.Available > 0)
        {
            int r;

            try {
                r = socket.ReceiveFrom(buffer, 0, World.MAX_UNRELIABLE_MESSAGE_SIZE, SocketFlags.None, ref _recvEndPoint);
            } catch (Exception e) {
                Debug.LogException(e);

                SocketNetDriverConnection conn;
                if (_udpConnections.TryGetValue(_recvEndPoint, out conn))
                {
                    callbacks.OnInvalidMessageReceived(conn);
                }

                continue;
            }

            if (r <= 0)
            {
                throw new SocketException((int)SocketError.SocketError);
            }

            metrics.bytesRecv += r;
            ++metrics.numPacketsRecv;

            SocketNetDriverConnection connection;
            if (_udpConnections.TryGetValue(_recvEndPoint, out connection))
            {
                if (connection.isValid)
                {
                    if (r > 3)
                    {
                        // currently NetMsgs are always more than 3 bytes, and this guarantees that we don't
                        // try to process a duplicated control udp control message.

                        callbacks.OnMessageReceived(connection, buffer, r);
                    }
                }
            }
            else
            {
                // is this a control code?
                var id = RecvControl(buffer, r);
                if (id != -1)
                {
                    for (int i = 0; i < _tcpConnections.Values.Count; ++i)
                    {
                        var c = _tcpConnections.Values[i];
                        if (c.channelID == id)
                        {
                            if (_udpConnections.Values.Contains(c))
                            {
                                Debug.LogWarning("UDP control message received for registered channel.");
                            }
                            else
                            {
                                c.udpEndpoint = new IPEndPoint(((IPEndPoint)_recvEndPoint).Address, ((IPEndPoint)_recvEndPoint).Port);
                                _udpConnections.Add(c.udpEndpoint, c);
                                SendTcpControlAck(c);
                                c.didHandshake = true;
                                callbacks.OnConnect(c);
                                break;
                            }
                        }
                    }
                }
            }
        }

        Perf.End();
    }
Exemple #18
0
	public bool IsDirty(ActorReplicationChannel channel, SerializableObject container, float dt, bool deltasOnly, bool hasReplicated, bool isOwner, bool netFlush, out object fieldValue, out bool deltaField) {
		Perf.Begin("FieldState.IsDirty");

		bool shouldReplicate = true;

		if (fieldSpec.replication.Condition != EReplicateCondition.Always) {
			switch (fieldSpec.replication.Condition) {
				case EReplicateCondition.InitialOnly:
					shouldReplicate = !hasReplicated;
				break;
				case EReplicateCondition.OwnerOnly:
					shouldReplicate = isOwner;
				break;
				case EReplicateCondition.SkipOwner:
					shouldReplicate = !isOwner;
				break;
				case EReplicateCondition.InitialOrOwner:
					shouldReplicate = !hasReplicated || isOwner;
				break;
				case EReplicateCondition.InitialOwnerOnly:
					shouldReplicate = !hasReplicated && isOwner;
				break;
			}
		}

		if (!shouldReplicate) {
			deltaField = false;
			fieldValue = null;
			Perf.End();
			return false;
		}

		if (!netFlush) {
			nextSendTime -= dt;
			if (nextSendTime > 0f) {
				deltaField = false;
				fieldValue = null;
				Perf.End();
				return false;
			}
		}

		// Update send time here: if we don't send because the value hasn't changed
		// we don't want to check again until after the UpdateRate has passed.
		nextSendTime = fieldSpec.replication.UpdateRate;
		
		fieldValue = fieldSpec.field.GetValue(container);

		// check ownerOnly object replication.
		if (fieldSpec.isObjectReference) {
			var actor = fieldValue as Actor;
			if ((actor != null) && actor.ownerOnly) {
				if (actor.ownerConnection != channel) {
					deltaField = false;
					Perf.End();
					return false;
				}
			}
		}

		deltaField = !fieldSpec.serializer.FieldsAreEqual(lastState, fieldValue);

		if (deltasOnly && !deltaField) {
			Perf.End();
			return false;
		}

		Perf.End();
		return true;
	}
Exemple #19
0
	void ReplicateObject(float dt, SerializableObject obj, Actor actor, ObjectReplicator replicator, bool isOwner, bool isRelevant, ref NetMsgs.ReplicatedObjectData msg) {
		Perf.Begin("ActorReplicationChannel.ReplicateObject");

		Assert.IsFalse((actor != null) ? actor.netTornOff : false);
		
		bool wroteAnything = false;

		// start on a byte boundary so we can restore the position to this point if we don't write any data.
		msg.archive.Flush();
		msg = msg.MaybeSend(connection);

		var position = msg.archive.Position;
		bool relevancyChanged = true;

		CHECK_FLD(msg.archive);

		if (replicator == null) {
			replicator = obj.internal_GetReplicator(connection);
		}

		if (replicator == null) {

			replicator = new ObjectReplicator(this, obj, connection.world.InternalGetReplicatedFields(obj), isOwner);
			obj.internal_SetReplicator(connection, replicator);
			
			msg.archive.Write((ushort)obj.netID);

			CHECK_FLD(msg.archive);

			// actor has not been replicated yet
			msg.archive.WriteUnsignedBits(1, 1);
			msg.archive.WriteUnsignedBits(isRelevant ? 1 : 0, 1);
			msg.archive.WriteUnsignedBits(((actor != null) && (actor.internal_NetTearOff)) ? 1 : 0, 1);

			CHECK_FLD(msg.archive);

			msg.archive.Write((ushort)((obj.outer is SerializableObject) ? (obj.outer as SerializableObject).netID : 0));
			msg.archive.Write(obj.classID);

			CHECK_FLD(msg.archive);

			replicator.FullSerialize(dt, msg.archive);
			SerializeCustomData(obj, msg.archive);
			wroteAnything = true;

		} else {

			relevancyChanged = replicator.wasRelevant != isRelevant;

			bool replicate = true;
			if ((dt >= 0f) && (actor != null) && !actor.internal_NetTearOff && !actor.internal_NetFlush && !relevancyChanged) {
				replicator.serializeDeltaTime += dt;
				if (replicator.serializeDeltaTime < actor.replicateRate) {
					replicate = false;
				}
            }

			if (replicate) {
				msg.archive.Write((ushort)obj.netID);
				CHECK_FLD(msg.archive);
				msg.archive.WriteUnsignedBits(0, 1);
				msg.archive.WriteUnsignedBits(isRelevant ? 1 : 0, 1);
				msg.archive.WriteUnsignedBits(((actor != null) && (actor.internal_NetTearOff)) ? 1 : 0, 1);
				CHECK_FLD(msg.archive);

				wroteAnything = replicator.DeltaSerialize(dt, msg.archive, (actor != null) && (actor.internal_NetFlush || relevancyChanged));
				wroteAnything = SerializeCustomData(obj, msg.archive) || wroteAnything;
			}
		}

		if (wroteAnything || ((actor != null) && (actor.internal_NetFlush || relevancyChanged))) {
			CHECK_FLD(msg.archive);
			obj.SerializeSubobjects(this);
		} else {
			msg.archive.Position = position;
			msg.archive.Discard();
		}

		replicator.wasRelevant = isRelevant;

		if ((actor != null) && actor.internal_NetTearOff) {
			obj.internal_SetReplicator(connection, null);
        }

		Perf.End();
	}
Exemple #20
0
	void InternalHandleReplicatedObjectData(NetMsgs.ReplicatedObjectData objectData) {
#if PROFILING
		try {
			Perf.Begin("ActorReplicationChannel.InternalHandleReplicatedObjectData");
#endif
			CHECK_FLD(objectData.archive);

			var netID = objectData.archive.ReadUShort();

			CHECK_FLD(objectData.archive);

			var obj = _connection.world.GetObjectByNetID(netID);

			var create = objectData.archive.ReadUnsignedBits(1) != 0;
			var relevant = objectData.archive.ReadUnsignedBits(1) != 0;
			var tearOff = objectData.archive.ReadUnsignedBits(1) != 0;

			CHECK_FLD(objectData.archive);

			ObjectReplicator replicator;

			if (obj == null) {
				if (!create) {
					throw new ActorReplicationException("Actor replication error (no actor with id " + netID + " and create flag not set)!");
				}
				var netIDOuter = objectData.archive.ReadUShort();
				var outerObj = _connection.world.GetObjectByNetID(netIDOuter);
				var classID = objectData.archive.ReadInt();
				CHECK_FLD(objectData.archive);
				obj = _connection.world.InternalCreateReplicatedObject(classID, netID);
				replicator = new ObjectReplicator(this, obj, _connection.world.InternalGetReplicatedFields(obj), false);
				obj.internal_SetReplicator(connection, replicator);
				obj.PreConstruct(outerObj);
				obj.PreNetConstruct();
			} else {
				if (create) {
					throw new ActorReplicationException("Actor replication error (actor with id " + netID + " create flag not set)!");
				}
				replicator = obj.internal_GetReplicator(connection);
			}

			var actor = obj as Actor;

			bool wasRelevant = true;
			if (actor != null) {
				wasRelevant = actor.isNetRelevant;
				actor.internal_NetRelevant = relevant;
			}

			obj.PreNetReceive();

			isSending = false;
			replicator.DeltaSerialize(0f, objectData.archive, false);
			obj.SerializeCustomData(objectData.archive);
			CHECK_FLD(objectData.archive);

			obj.PostNetReceive();

			if (create) {
				obj.Construct();
				obj.PostNetConstruct();
				obj.PostConstruct();
			}

			replicator.OnRep();
			obj.PostOnRepFields();

			if (create && (actor != null) && !_connection.world.isTraveling) {
				actor.OnLevelStart();
			}

			IntHashtableList<ObjectReplicator> repls;
			if (pendingRefs.TryGetValue(obj.netIDHashCode, out repls)) {
				for (int i = 0; i < repls.Values.Count; ++i) {
					repls.Values[i].ResolveReference(obj, netID);
				}
				for (int i = 0; i < repls.Values.Count; ++i) {
					repls.Values[i].OnRep();
				}
				repls.Clear();
			}

			if ((actor != null) && (wasRelevant != relevant)) {
				actor.OnNetRelevancyChanged();
			}

			if ((actor != null) && tearOff) {
				obj.internal_SetReplicator(connection, null);
				actor.NetTearOff();
			}

#if PROFILING
		} finally {
			Perf.End();
		}
#endif
	}