示例#1
0
    void RawNetRecv(ActorReplicationChannel channel, int size)
    {
#if PROFILING
        try {
            Perf.Begin("World.RawNetRecv");
#endif
        _netArchive.BeginRead(size);
        int typeID = _netArchive.ReadInt();
        NetMsg msg = _netMsgFactory.GetNetMsg(typeID);
        if (msg != null)
        {
            msg.Serialize(channel.connection, _netArchive);
            if (_netArchive.hasUnreadBytes)
            {
                throw new System.IO.IOException(msg.GetType().FullName + " did not consume its entire payload.");
            }
            DynamicDispatchNetMsg(msg, channel);
        }
        else
        {
            throw new System.IO.IOException("Unrecognized net message type " + typeID);
        }
#if PROFILING
    }

    finally {
        Perf.End();
    }
#endif
    }
示例#2
0
    public void TickServer(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics)
    {
        Perf.Begin("LocalGameNetDriver.TickServer");

        if (serverSend != null)
        {
            if (serverSend.connectPending)
            {
                serverSend.connectPending = false;
                Assert.IsNotNull(clientSend);
                clientSend.connectPending = true;
                serverSend.callbacks.OnConnect(serverSend);
            }

            if ((serverSend != null) && (clientSendOfs > 0))
            {
                RecvMessages(clientSendBuffer, clientSendOfs, recvBuffer, serverSend, ref reliableChannelMetrics, ref unreliableChannelMetrics);
                clientSendOfs = 0;
            }

            if ((serverSend != null) && (serverSend.disconnectPending))
            {
                serverSend.Dispose();
                serverSend = null;
            }
        }

        Perf.End();
    }
示例#3
0
    protected virtual void TickActors(MonoBehaviour loadingContext)
    {
        Perf.Begin("World.TickActors");

        _loadingQueue.Run(loadingContext);
        _taskQueue.Run(loadingContext);

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

            if (!actor.pendingKill)
            {
                actor.Tick();
                actor.TickComponents();
                actor.TickLifetime();
            }

            if (actor.pendingKill)
            {
                DestroyActor(actor, false);
                _actors.RemoveAt(i);
            }
            else
            {
                ++i;
            }
        }

        Perf.End();
    }
示例#4
0
 public void SendReliable(byte[] buffer, int numBytes)
 {
     Perf.Begin("LocalGameNetDriverConnection.SendReliable");
     netDriver.SendReliable(this, buffer, numBytes);
     reliableMetrics.bytesSent += numBytes;
     ++reliableMetrics.numPacketsSent;
     Perf.End();
 }
示例#5
0
	void ReplicateDependencies(ref NetMsgs.ReplicatedObjectData packet) {
		Perf.Begin("ActorReplicationChannel.ReplicateDependencies");

		// Serialize referenced actors.
		objectRefs2.Clear();

		while (objectRefs.Values.Count > 0) {
			Utils.Swap(ref objectRefs, ref objectRefs2);

			for (int i = 0; i < objectRefs2.Values.Count; ++i) {
				int netIDHashCode = objectRefs2.Values[i];
				var obj = connection.world.GetObjectByNetIDHashCode(netIDHashCode);

				bool isOwner = true;
				bool isRelevant = true;
				var actor = obj as Actor;
				ObjectReplicator replicator = null;

				if (actor != null) {
					Assert.IsFalse(actor.disposed);
					if (actor.internal_NetTearOff) {
						continue;
					}
					isOwner = actor.ownerConnectionID == _connection.id;
					if (!isOwner && actor.ownerOnly) {
						// actor is not replicated on this channel.
						continue;
					}
					if (!CheckRelevancy(actor, out replicator, out isRelevant)) {
						// actor is not replicated on this channel.
						continue;
					}
				} else {
					var component = obj as ActorComponent;

					if (component != null) {
						isOwner = component.owner.ownerConnectionID == _connection.id;
						if (!isOwner && component.owner.ownerOnly) {
							// only replicate to owner.
							continue;
						}
					}
				}

				ReplicateObject(0f, obj, actor, replicator, isOwner, isRelevant, ref packet);
#if !PACKET_COMBINE
				packet = packet.Flush(connection);
#endif
			}

			objectRefs2.Clear();
		}

		Perf.End();
	}
示例#6
0
	public void Write(NetArchive archive, ISerializableObjectReferenceCollector collector, object fieldVal, bool deltaField) {
		Perf.Begin("FieldState.Write");

		fieldSpec.serializer.Serialize(archive, collector, ref fieldVal, deltaField ? lastState : null);

		if (deltaField) {
			lastState = fieldSpec.serializer.Copy(fieldVal);
		}

		Perf.End();
	}
示例#7
0
	public void ReplicateRPC(SerializableObject context, int rpcID, ObjectRPCSerializer serializer, params object[] args) {
		if (!_connection.isValid) {
			return;
		}

		Perf.Begin("ActorReplicationChannel.ReplicateRPC");

		if (isServer) {
			if (!didHandshake) {
				// client hasn't finished connecting
				Perf.End();
				return;
			}

			if ((clientLevel == null) || (clientLevel != _connection.world.currentLevel)) {
				Perf.End();
				return;
			}
		} else if (_connection.world.isTraveling) {
			Perf.End();
			return;
		}

		if (context.internal_GetReplicator(connection) == null) {
			// has not been replicated.
			Perf.End();
			return;
		}

		var actor = context as Actor;
		if ((actor != null) && isServer && serializer.rpcInfo.CheckRelevancy && !actor.IsNetRelevantFor(this)) {
			// not relevant
			Perf.End();
			return;
		}

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

		objectRefs.Clear();

		var netMsg = NetMsgs.ReplicatedObjectRPC.New(context.netID, (ushort)rpcID);
		serializer.Write(netMsg.archive, this, args);
		
		if (_connection.world is Server.ServerWorld) {
			// send objects in the argument list first
			ReplicateDependencies();
		} else {
			objectRefs.Clear();
		}

		_connection.SendReliable(netMsg);

		Perf.End();
	}
示例#8
0
 internal void SendReliable(LocalGameNetDriverConnection conn, byte[] buffer, int numBytes)
 {
     Perf.Begin("LocalGameNetDriver.SendReliable");
     if (conn == serverSend)
     {
         WriteMessage(buffer, numBytes, serverSendBuffer, ref serverSendOfs);
     }
     else
     {
         Assert.IsNotNull(clientSend);
         WriteMessage(buffer, numBytes, clientSendBuffer, ref clientSendOfs);
     }
     Perf.End();
 }
示例#9
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;
	}
示例#10
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();
	}
示例#11
0
    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 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();
    }
    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 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();
    }
示例#15
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();
    }
示例#16
0
    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();
    }
示例#17
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;
		}
	}
    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();
    }
示例#19
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;
	}
    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();
    }
示例#22
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();
	}
示例#23
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();
	}
示例#24
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
	}