Example #1
0
        void Connect(ConnectionDetails details, Controller controller) {
            Active = true;

            var client = new Client(details.Nickname, details.SteamworksSessionId);
            var connection = Connection.CreateWith(details);
            var handshaker = new Handshaker(details, client, connection);
            var signonProcessor = new SignonProcessor(client, connection);
            var gameProcessor = new GameProcessor(client, connection);
            var userCmdGenerator = new UserCmdGenerator(client, connection);

            controller.Initialize(details.SteamId, client, connection, userCmdGenerator);

            Machines.Call tick = () => {
                controller.Tick();
                userCmdGenerator.Tick();
                client.Created.Clear();
                client.Deleted.Clear();
            };
            Machines.Call joinReset = () => {
                userCmdGenerator.Reset();
            };

            var metastates = new Dictionary<SpectateState, Metastate>() {
                { SpectateState.HANDSHAKE_REQUEST, Metastate.HANDSHAKE },
                { SpectateState.HANDSHAKE_CONNECT, Metastate.HANDSHAKE },
                { SpectateState.SIGNON_CONNECTED, Metastate.SIGNON },
                { SpectateState.SIGNON_NEW, Metastate.SIGNON },
                { SpectateState.SIGNON_PRESPAWN, Metastate.SIGNON },
                { SpectateState.SIGNON_SPAWN, Metastate.SIGNON },
                { SpectateState.SIGNON_FULL, Metastate.GAME },
            };

            var processors = new Dictionary<Metastate, Processor>() { 
                { Metastate.HANDSHAKE, handshaker },
                { Metastate.SIGNON, signonProcessor},
                { Metastate.GAME, gameProcessor }
            };

            Func<SpectateState, Machines.MachineBinding<Event, SpectateState>> Start = Machines.Start<Event, SpectateState>;
            Func<SpectateState, Machines.MachineStateBinding<Event, SpectateState>> In = Machines.In<Event, SpectateState>;
            Func<Event, Machines.MachineTransitionBinding<Event, SpectateState>> On = Machines.On<Event, SpectateState>;
            var machine = Start(SpectateState.DISCONNECTED)
                .Add(In(SpectateState.DISCONNECTED)
                    .Add(On(Event.REQUEST_CONNECT).Transit(SpectateState.HANDSHAKE_REQUEST)))
                .Add(In(SpectateState.HANDSHAKE_REQUEST)
                    .Entry(handshaker.RequestHandshake)
                    .Add(On(Event.HANDSHAKE_CHALLENGE).Transit(SpectateState.HANDSHAKE_CONNECT))
                    .Add(On(Event.REJECTED).Transit(SpectateState.REJECTED)))
                .Add(In(SpectateState.HANDSHAKE_CONNECT)
                    .Entry(handshaker.RespondHandshake)
                    .Add(On(Event.HANDSHAKE_COMPLETE).Transit(SpectateState.SIGNON_CONNECTED))
                    .Add(On(Event.REJECTED).Transit(SpectateState.REJECTED)))
                .Add(In(SpectateState.SIGNON_CONNECTED)
                    .Entry(signonProcessor.EnterConnected)
                    .Add(On(Event.GO_NEW).Transit(SpectateState.SIGNON_NEW))
                    .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                .Add(In(SpectateState.SIGNON_NEW)
                    .Entry(signonProcessor.EnterNew)
                    .Add(On(Event.GO_CONNECTED).Transit(SpectateState.SIGNON_CONNECTED))
                    .Add(On(Event.GO_PRESPAWN).Transit(SpectateState.SIGNON_PRESPAWN))
                    .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                .Add(In(SpectateState.SIGNON_PRESPAWN)
                    .Entry(signonProcessor.EnterPrespawn)
                    .Add(On(Event.GO_SPAWN).Transit(SpectateState.SIGNON_SPAWN))
                    .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                .Add(In(SpectateState.SIGNON_SPAWN)
                    .Entry(signonProcessor.EnterSpawn)
                    .Add(On(Event.BASELINE).Transit(SpectateState.SIGNON_FULL))
                    .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                .Add(In(SpectateState.SIGNON_FULL)
                    .Entry(() => { gameProcessor.EnterGame(); joinReset(); })
                    .Add(On(Event.TICK).Call(tick))
                    .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                .Add(In(SpectateState.REJECTED))
                .Build();

            machine.Trigger(Event.REQUEST_CONNECT);

            long next_tick = DateTime.Now.Ticks;
            while (machine.State != SpectateState.DISCONNECTED &&
                   machine.State != SpectateState.REJECTED) {
                if (next_tick > DateTime.Now.Ticks) {
                    Thread.Sleep(1);
                    continue;
                }

                List<byte[]> outBand = connection.GetOutOfBand();
                List<Connection.Message> inBand = connection.GetInBand();

                foreach (byte[] message in outBand) {
                    Nullable<Event> e = processors[metastates[machine.State]].Process(message);
                    if (e.HasValue) {
                        machine.Trigger(e.Value);
                    }
                }

                foreach (Connection.Message message in inBand) {
                    Nullable<Event> e = processors[metastates[machine.State]].Process(message);
                    if (e.HasValue) {
                        machine.Trigger(e.Value);
                    }
                }

                machine.Trigger(Event.TICK);

                if (client.TickInterval > 0) {
                    next_tick += (uint) (client.TickInterval * 1000 * 10000 /* ticks per ms */);
                } else {
                    next_tick += 50 * 1000;
                }
                int remain = (int) (next_tick - DateTime.Now.Ticks) / 10000;
                if (remain > 0) {
                    Thread.Sleep(1);
                } else if (remain < 0) {
                    next_tick = DateTime.Now.Ticks;
                }
            }

            Active = false;
            if (machine.State == SpectateState.DISCONNECTED) {
            } else if (machine.State == SpectateState.REJECTED) {
            } else {
                throw new Exception("Unknown state " + machine.State);
            }
        }
Example #2
0
File: Lara.cs Project: sy1989/nora
        void Connect(ConnectionDetails details, Controller controller)
        {
            Active = true;

            var client           = new Client(details.Nickname, details.SteamworksSessionId);
            var connection       = Connection.CreateWith(details);
            var handshaker       = new Handshaker(details, client, connection);
            var signonProcessor  = new SignonProcessor(client, connection);
            var gameProcessor    = new GameProcessor(client, connection);
            var userCmdGenerator = new UserCmdGenerator(client, connection);

            controller.Initialize(details.SteamId, client, connection, userCmdGenerator);

            Machines.Call tick = () => {
                controller.Tick();
                userCmdGenerator.Tick();
                client.Created.Clear();
                client.Deleted.Clear();
            };
            Machines.Call joinReset = () => {
                userCmdGenerator.Reset();
            };

            var metastates = new Dictionary <SpectateState, Metastate>()
            {
                { SpectateState.HANDSHAKE_REQUEST, Metastate.HANDSHAKE },
                { SpectateState.HANDSHAKE_CONNECT, Metastate.HANDSHAKE },
                { SpectateState.SIGNON_CONNECTED, Metastate.SIGNON },
                { SpectateState.SIGNON_NEW, Metastate.SIGNON },
                { SpectateState.SIGNON_PRESPAWN, Metastate.SIGNON },
                { SpectateState.SIGNON_SPAWN, Metastate.SIGNON },
                { SpectateState.SIGNON_FULL, Metastate.GAME },
            };

            var processors = new Dictionary <Metastate, Processor>()
            {
                { Metastate.HANDSHAKE, handshaker },
                { Metastate.SIGNON, signonProcessor },
                { Metastate.GAME, gameProcessor }
            };

            Func <SpectateState, Machines.MachineBinding <Event, SpectateState> >      Start = Machines.Start <Event, SpectateState>;
            Func <SpectateState, Machines.MachineStateBinding <Event, SpectateState> > In    = Machines.In <Event, SpectateState>;
            Func <Event, Machines.MachineTransitionBinding <Event, SpectateState> >    On    = Machines.On <Event, SpectateState>;
            var machine = Start(SpectateState.DISCONNECTED)
                          .Add(In(SpectateState.DISCONNECTED)
                               .Add(On(Event.REQUEST_CONNECT).Transit(SpectateState.HANDSHAKE_REQUEST)))
                          .Add(In(SpectateState.HANDSHAKE_REQUEST)
                               .Entry(handshaker.RequestHandshake)
                               .Add(On(Event.HANDSHAKE_CHALLENGE).Transit(SpectateState.HANDSHAKE_CONNECT))
                               .Add(On(Event.REJECTED).Transit(SpectateState.REJECTED)))
                          .Add(In(SpectateState.HANDSHAKE_CONNECT)
                               .Entry(handshaker.RespondHandshake)
                               .Add(On(Event.HANDSHAKE_COMPLETE).Transit(SpectateState.SIGNON_CONNECTED))
                               .Add(On(Event.REJECTED).Transit(SpectateState.REJECTED)))
                          .Add(In(SpectateState.SIGNON_CONNECTED)
                               .Entry(signonProcessor.EnterConnected)
                               .Add(On(Event.GO_NEW).Transit(SpectateState.SIGNON_NEW))
                               .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                          .Add(In(SpectateState.SIGNON_NEW)
                               .Entry(signonProcessor.EnterNew)
                               .Add(On(Event.GO_CONNECTED).Transit(SpectateState.SIGNON_CONNECTED))
                               .Add(On(Event.GO_PRESPAWN).Transit(SpectateState.SIGNON_PRESPAWN))
                               .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                          .Add(In(SpectateState.SIGNON_PRESPAWN)
                               .Entry(signonProcessor.EnterPrespawn)
                               .Add(On(Event.GO_SPAWN).Transit(SpectateState.SIGNON_SPAWN))
                               .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                          .Add(In(SpectateState.SIGNON_SPAWN)
                               .Entry(signonProcessor.EnterSpawn)
                               .Add(On(Event.BASELINE).Transit(SpectateState.SIGNON_FULL))
                               .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                          .Add(In(SpectateState.SIGNON_FULL)
                               .Entry(() => { gameProcessor.EnterGame(); joinReset(); })
                               .Add(On(Event.TICK).Call(tick))
                               .Add(On(Event.DISCONNECTED).Transit(SpectateState.DISCONNECTED)))
                          .Add(In(SpectateState.REJECTED))
                          .Build();

            machine.Trigger(Event.REQUEST_CONNECT);

            long next_tick = DateTime.Now.Ticks;

            while (machine.State != SpectateState.DISCONNECTED &&
                   machine.State != SpectateState.REJECTED)
            {
                if (next_tick > DateTime.Now.Ticks)
                {
                    Thread.Sleep(1);
                    continue;
                }

                List <byte[]>             outBand = connection.GetOutOfBand();
                List <Connection.Message> inBand  = connection.GetInBand();

                foreach (byte[] message in outBand)
                {
                    Nullable <Event> e = processors[metastates[machine.State]].Process(message);
                    if (e.HasValue)
                    {
                        machine.Trigger(e.Value);
                    }
                }

                foreach (Connection.Message message in inBand)
                {
                    Nullable <Event> e = processors[metastates[machine.State]].Process(message);
                    if (e.HasValue)
                    {
                        machine.Trigger(e.Value);
                    }
                }

                machine.Trigger(Event.TICK);

                if (client.TickInterval > 0)
                {
                    next_tick += (uint)(client.TickInterval * 1000 * 10000 /* ticks per ms */);
                }
                else
                {
                    next_tick += 50 * 1000;
                }
                int remain = (int)(next_tick - DateTime.Now.Ticks) / 10000;
                if (remain > 0)
                {
                    Thread.Sleep(1);
                }
                else if (remain < 0)
                {
                    next_tick = DateTime.Now.Ticks;
                }
            }

            Active = false;
            if (machine.State == SpectateState.DISCONNECTED)
            {
            }
            else if (machine.State == SpectateState.REJECTED)
            {
            }
            else
            {
                throw new Exception("Unknown state " + machine.State);
            }
        }