The Mx dispatcher; this handles receiving messages on the UDP client and dispatching them to the correct connected Mx client.
예제 #1
0
 public MxClientGroup(MxDispatcher dispatcher, string identifier)
 {
     _dispatcher     = dispatcher;
     Identifier      = identifier;
     RealtimeClients = new List <MxClient>();
     ReliableClients = new List <MxReliability>();
 }
예제 #2
0
 public TychaiaServer(int realtimePort, int reliablePort)
 {
     this.m_MxDispatcher = new MxDispatcher(realtimePort, reliablePort);
     this.m_MxDispatcher.MessageReceived += this.OnMessageReceived;
     this.m_MxDispatcher.ClientDisconnected += this.OnClientDisconnected;
     this.m_MessageEvents = new Dictionary<string, Action<MxClient, byte[]>>();
 }
예제 #3
0
 public void AttachNetworkDispatcher(MxDispatcher dispatcher)
 {
     this.m_MxDispatcher = dispatcher;
     this.m_MxDispatcher.ReliableSendProgress += this.MxDispatcherOnReliableSendProgress;
     this.m_MxDispatcher.ReliableReceivedProgress += this.MxDispatcherOnReliableReceivedProgress;
     this.m_MxDispatcher.MessageReceived += this.MxDispatcherOnMessageReceived;
     this.m_MxDispatcher.MessageAcknowledged += this.MxDispatcherOnMessageAcknowledged;
 }
예제 #4
0
 /// <summary>
 /// Internally handles propagating network messages to the networked components on the client.
 /// </summary>
 /// <param name="component"></param>
 /// <param name="gameContext"></param>
 /// <param name="updateContext"></param>
 /// <param name="dispatcher"></param>
 /// <param name="client"></param>
 /// <param name="payload"></param>
 /// <param name="protocolId"></param>
 /// <param name="eventState"></param>
 private void ClientMessageCallback(
     INetworkedComponent component,
     IGameContext gameContext,
     IUpdateContext updateContext,
     MxDispatcher dispatcher,
     MxClient client,
     byte[] payload,
     uint protocolId,
     EventState eventState)
 {
     if (!eventState.Consumed)
     {
         eventState.Consumed = component.ReceiveMessage(this, gameContext,
                                                        updateContext,
                                                        dispatcher,
                                                        client,
                                                        payload,
                                                        protocolId);
     }
 }
예제 #5
0
        public TychaiaClient(int realtimePort, int reliablePort)
        {
            this.m_MxDispatcher = new MxDispatcher(realtimePort, reliablePort);
            this.m_MxDispatcher.MessageReceived += this.OnMessageReceived;
            this.m_MxDispatcher.ClientDisconnectWarning += this.OnClientDisconnectWarning;
            this.m_MxDispatcher.ClientDisconnected += this.OnClientDisconnected;
            this.m_MessageEvents = new Dictionary<string, Action<MxClient, byte[]>>();

            this.PlayersInGame = new string[0];
            this.m_LastUpdateCall = new DateTime(1970, 1, 1, 0, 0, 0);
            this.m_LastDisconnectionWarningTime = new DateTime(1970, 1, 1, 0, 0, 0);

            this.ListenForMessage(
                "player list",
                (mxc, data) =>
                {
                    var list = InMemorySerializer.Deserialize<PlayerList>(data);
                    this.PlayersInGame = list.Players ?? new string[0];
                });
        }
예제 #6
0
파일: Program.cs 프로젝트: TreeSeed/Tychaia
        public static void Main(string[] args)
        {
            var dispatcher = new MxDispatcher(int.Parse(args[0]), int.Parse(args[0]) + 1);

            dispatcher.Connect(new DualIPEndPoint(IPAddress.Parse(args[1]), int.Parse(args[2]), int.Parse(args[2]) + 1));

            dispatcher.MessageSent += (sender, eventArgs) => Console.WriteLine("message sent " + Encoding.ASCII.GetString(eventArgs.Payload));
            dispatcher.MessageReceived += (sender, eventArgs) => Console.WriteLine("message received " + Encoding.ASCII.GetString(eventArgs.Payload));
            dispatcher.MessageLost += (sender, eventArgs) => Console.WriteLine("message lost " + Encoding.ASCII.GetString(eventArgs.Payload));
            dispatcher.MessageAcknowledged += (sender, eventArgs) => Console.WriteLine("message acknowledged " + Encoding.ASCII.GetString(eventArgs.Payload));

            var array = new[] { "hello", "world", "what", "is", "this", "i", "don't", "even" };
            var counter = 0;
            var accumulator = 0;

            while (true)
            {
                accumulator += 1;

                if (accumulator == 10)
                {
                    foreach (var endpoint in dispatcher.Endpoints)
                    {
                        dispatcher.Send(endpoint, Encoding.ASCII.GetBytes(array[counter]));
                    }

                    counter++;
                    if (counter >= array.Length)
                    {
                        counter = 0;
                    }

                    accumulator = 0;
                }

                dispatcher.Update();

                Thread.Sleep(1000 / 30);
            }
        }
        public DefaultNetworkAPI(bool join, IPAddress address)
        {
            if (!join)
            {
                this.m_MxDispatcher = new MxDispatcher(9000, 9001);
            }
            else
            {
                this.m_MxDispatcher = new MxDispatcher(9002, 9003);
            }
            this.m_MxDispatcher.MessageReceived += this.OnMessageReceived;
            this.m_MxDispatcher.ClientDisconnected += this.OnClientDisconnected;
            this.m_MxDispatcher.ClientDisconnectWarning += this.OnClientDisconnectWarning;

            this.m_MessageEvents = new Dictionary<string, List<Action<string>>>();

            this.WasJoin = join;

            if (join)
            {
                this.m_MxDispatcher.Connect(new DualIPEndPoint(address, 9000, 9001));
            }
        }
예제 #8
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MxClient"/> class.
        /// </summary>
        /// <param name="dispatcher">
        ///     The dispatcher that is creating this client.
        /// </param>
        /// <param name="mxClientGroup"></param>
        /// <param name="target">
        ///     The target endpoint for the Mx client.
        /// </param>
        /// <param name="sharedUdpClient">
        ///     The shared UDP client with which to send messages.
        /// </param>
        public MxClient(MxDispatcher dispatcher, MxClientGroup mxClientGroup, IPEndPoint target, UdpClient sharedUdpClient)
        {
            _dispatcher                 = dispatcher;
            Group                       = mxClientGroup;
            _targetEndPoint             = target;
            _sharedUdpClient            = sharedUdpClient;
            _receivedPackets            = new Queue <byte[]>();
            _pendingRealtimeSendPackets = new Queue <byte[]>();
            _pendingReliableSendPackets = new Queue <byte[]>();
            _lastCall                   = DateTime.Now;
            _deltaTime                  = 1000.0 / 30.0;

            // Initialize connection information.
            _disconnectAccumulator  = 0;
            _disconnectLimit        = 900;
            _disconnectWarningLimit = 30;
            _receiveQueue           = new List <bool>();
            for (var i = 0; i < 32; i++)
            {
                _receiveQueue.Add(false);
            }

            _rttQueue                      = new List <ulong>();
            _sendQueue                     = new Dictionary <uint, ulong>();
            _sendMessageQueue              = new Dictionary <uint, KeyValuePair <uint, byte[][]> >();
            _localSequenceNumber           = 0;
            _remoteSequenceNumber          = uint.MaxValue;
            _sendAccumulator               = 0;
            _rttThreshold                  = 250.0;
            _fcIsGoodSendMode              = false;
            _fcPenaltyTime                 = 4.0;
            _fcGoodConditionsTime          = 0;
            _fcPenaltyReductionAccumulator = 0;

            HasReceivedPacket = false;
        }
예제 #9
0
        public void Send <T>(MxDispatcher dispatcher, MxClientGroup target, T message, bool reliable = false)
        {
            if (target.RealtimeClients.Count == 0)
            {
                throw new InvalidOperationException(
                          "Attempted to send message to group " + target +
                          ", but it has no clients.");
            }

            var serialized = _networkMessageSerialization.Serialize(message);

            dispatcher.Send(target, serialized, reliable);

            var type = typeof(T);

            if (!_currentNetworkFrame.BytesSentByMessageType.ContainsKey(type))
            {
                _currentNetworkFrame.BytesSentByMessageType[type]    = 0;
                _currentNetworkFrame.MessagesSentByMessageType[type] = 0;
            }

            _currentNetworkFrame.BytesSentByMessageType[type] += serialized.Length;
            _currentNetworkFrame.MessagesSentByMessageType[type]++;
        }
예제 #10
0
        /// <summary>
        /// Initializes a new instance of the <see cref="MxClient"/> class.
        /// </summary>
        /// <param name="dispatcher">
        /// The dispatcher that is creating this client.
        /// </param>
        /// <param name="target">
        /// The target endpoint for the Mx client.
        /// </param>
        /// <param name="sharedUdpClient">
        /// The shared UDP client with which to send messages.
        /// </param>
        public MxClient(
            MxDispatcher dispatcher,
            IPEndPoint target,
            UdpClient sharedUdpClient)
        {
            this.m_Dispatcher                 = dispatcher;
            this.m_TargetEndPoint             = target;
            this.m_SharedUdpClient            = sharedUdpClient;
            this.m_ReceivedPackets            = new Queue <byte[]>();
            this.m_PendingRealtimeSendPackets = new Queue <byte[]>();
            this.m_PendingReliableSendPackets = new Queue <byte[]>();
            this.m_LastCall  = DateTime.Now;
            this.m_DeltaTime = 1000.0 / 30.0;

            // Initialize connection information.
            this.m_DisconnectAccumulator  = 0;
            this.m_DisconnectLimit        = 900;
            this.m_DisconnectWarningLimit = 30;
            this.m_ReceiveQueue           = new List <bool>();
            for (var i = 0; i < 32; i++)
            {
                this.m_ReceiveQueue.Add(false);
            }

            this.m_RTTQueue                      = new List <ulong>();
            this.m_SendQueue                     = new Dictionary <uint, ulong>();
            this.m_SendMessageQueue              = new Dictionary <uint, KeyValuePair <uint, byte[][]> >();
            this.m_LocalSequenceNumber           = 0;
            this.m_RemoteSequenceNumber          = uint.MaxValue;
            this.m_SendAccumulator               = 0;
            this.m_RTTThreshold                  = 250.0;
            this.m_FCIsGoodSendMode              = false;
            this.m_FCPenaltyTime                 = 4.0;
            this.m_FCGoodConditionsTime          = 0;
            this.m_FCPenaltyReductionAccumulator = 0;
        }
예제 #11
0
 /// <summary>
 /// The detach network dispatcher.
 /// </summary>
 /// <param name="dispatcher">
 /// The dispatcher.
 /// </param>
 public void DetachNetworkDispatcher(MxDispatcher dispatcher)
 {
 }
예제 #12
0
 public void Dispose()
 {
     // This will unregister the events.
     Dispatcher = null;
 }
예제 #13
0
 public void Dispose()
 {
     // This will unregister the events.
     Dispatcher = null;
 }
예제 #14
0
 /// <summary>
 /// The detach network dispatcher.
 /// </summary>
 /// <param name="dispatcher">
 /// The dispatcher.
 /// </param>
 public void DetachNetworkDispatcher(MxDispatcher dispatcher)
 {
 }
        public bool ReceiveMessage(ComponentizedEntity entity, IServerContext serverContext, IUpdateContext updateContext, MxDispatcher dispatcher, MxClient client, byte[] payload, uint protocolId)
        {
            if (!_enabled)
            {
                return(false);
            }

            if (_uniqueIdentifierForEntity == null)
            {
                return(false);
            }

            // See what kind of messages we accept, based on the client authority.
            switch (ClientAuthoritiveMode)
            {
            case ClientAuthoritiveMode.None:
                // We don't accept any client data about this entity, so ignore it.
                return(false);

            case ClientAuthoritiveMode.TrustClient:
            {
                // Check to see if the message is coming from a client that has authority.
                if (ClientOwnership != null && ClientOwnership != client.Group)
                {
                    // We don't trust this message.
                    return(false);
                }

                // We trust the client, so process this information like a client would.
                var propertyMessage = _networkMessageSerialization.Deserialize(payload) as EntityPropertiesMessage;

                if (propertyMessage == null || propertyMessage.EntityID != _uniqueIdentifierForEntity.Value)
                {
                    return(false);
                }

                // If the entity is a synchronised entity, collect properties of the synchronised object
                // directly.
                var synchronisedEntity = entity as ISynchronisedObject;
                if (synchronisedEntity != null)
                {
                    _synchronisationContext = synchronisedEntity;
                    _synchronisationContext.DeclareSynchronisedProperties(this);
                }

                // Iterate through all the components on the entity and get their synchronisation data as well.
                foreach (var synchronisedComponent in entity.Components.OfType <ISynchronisedObject>())
                {
                    _synchronisationContext = synchronisedComponent;
                    _synchronisationContext.DeclareSynchronisedProperties(this);
                }

                AssignMessageToSyncData(propertyMessage, _synchronisedData, client.Group);
                return(true);
            }

            case ClientAuthoritiveMode.ReplayInputs:
                // We don't implement this yet, but we don't want to allow client packets to cause
                // a server error, so silently consume it.
                return(false);
            }

            return(false);
        }
        public bool ReceiveMessage(ComponentizedEntity entity, IGameContext gameContext, IUpdateContext updateContext, MxDispatcher dispatcher, MxClient server,
                                   byte[] payload, uint protocolId)
        {
            if (!_enabled)
            {
                return(false);
            }

            if (_uniqueIdentifierForEntity == null)
            {
                return(false);
            }

            var propertyMessage = _networkMessageSerialization.Deserialize(payload) as EntityPropertiesMessage;

            if (propertyMessage == null || propertyMessage.EntityID != _uniqueIdentifierForEntity.Value)
            {
                return(false);
            }

            // If the entity is a synchronised entity, collect properties of the synchronised object
            // directly.
            var synchronisedEntity = entity as ISynchronisedObject;

            if (synchronisedEntity != null)
            {
                _synchronisationContext = synchronisedEntity;
                _synchronisationContext.DeclareSynchronisedProperties(this);
            }

            // Iterate through all the components on the entity and get their synchronisation data as well.
            foreach (var synchronisedComponent in entity.Components.OfType <ISynchronisedObject>())
            {
                _synchronisationContext = synchronisedComponent;
                _synchronisationContext.DeclareSynchronisedProperties(this);
            }

            AssignMessageToSyncData(propertyMessage, _synchronisedData, server.Group);
            return(true);
        }
예제 #17
0
 public void AttachDispatcher(IWorld world, MxDispatcher dispatcher)
 {
     _dispatchers[world]       = dispatcher;
     _dispatcherChanged[world] = true;
 }
예제 #18
0
 public void AttachDispatcher(IServerWorld world, MxDispatcher dispatcher)
 {
     _serverDispatchers[world]       = dispatcher;
     _serverDispatcherChanged[world] = true;
 }
예제 #19
0
        public void DetachNetworkDispatcher(MxDispatcher dispatcher)
        {
            if (this.m_MxDispatcher != dispatcher)
            {
                return;
            }

            this.m_MxDispatcher.ReliableSendProgress -= this.MxDispatcherOnReliableSendProgress;
            this.m_MxDispatcher.ReliableReceivedProgress -= this.MxDispatcherOnReliableReceivedProgress;
            this.m_MxDispatcher.MessageReceived -= this.MxDispatcherOnMessageReceived;
            this.m_MxDispatcher.MessageAcknowledged -= this.MxDispatcherOnMessageAcknowledged;
            this.m_MxDispatcher = null;
        }