Пример #1
0
 public MachineStateBinding(S state)
 {
     this.state       = state;
     this.enter       = null;
     this.exit        = null;
     this.transitions = new List <MachineTransitionBinding <E, S> >();
 }
Пример #2
0
        private static BufferedMachine <Event, State> MakeMachine(
            SteamBot bot, Client client)
        {
            Machines.Call connect = () => {
                bot.Connect();
            };
            Machines.Call open = () => {
                bot.SetFriendsOnline(bot.Logon.Username);
                client.Launch(Games.DotaGameId);
            };
            Machines.Call sayHello = () => {
                client.SayHello();
            };
            Machines.Call leaveLobby = () => {
                if (client.Lobby.connect == null)
                {
                    client.LeaveLobby();
                }
                else
                {
                    client.AbandonCurrentGame();
                }
            };
            Machines.Call getTicket = () => {
                client.GetAppTicket();
            };
            Machines.Call createLobby = () => {
                client.CreateLobby("cow");
            };
            Machines.Call joinRadiant = () => {
                client.JoinLobbySlot(
                    SteamKit2.GC.Dota.Internal.DOTA_GC_TEAM.DOTA_GC_TEAM_GOOD_GUYS);
            };
            Machines.Call startLobby = () => {
                client.LaunchLobby();
            };
            Machines.Call getAuth = () => {
                client.CreateAuthTicket();
                client.Auth();
            };
            Machines.Call beginSession = () => {
                client.BeginGameServerSession();
            };
            Machines.Call join = () => {
                string[] split    = client.Lobby.connect.Split(':');
                var      endpoint = new IPEndPoint(IPAddress.Parse(split[0]), Int16.Parse(split[1]));

                Lara.Join(new ConnectionDetails()
                {
                    Endpoint            = endpoint,
                    SteamId             = bot.Client.SteamID.ConvertToUInt64(),
                    Nickname            = bot.Logon.Username,
                    SteamworksSessionId = client.SteamworksSessionId,
                    Ticket = client.TicketForServer,
                    Secret = client.Lobby.pass_key
                }, new AshlyController());
            };

            Func <State, Machines.MachineBinding <Event, State> > Start =
                Machines.Start <Event, State>;
            Func <State, Machines.MachineStateBinding <Event, State> > In =
                Machines.In <Event, State>;
            Func <Event, Machines.MachineTransitionBinding <Event, State> > On =
                Machines.On <Event, State>;
            var unbuffered = Start(State.CONCEIVED)
                             .Add(In(State.CONCEIVED)
                                  .Add(On(Event.OPEN_REQUEST).Transit(State.CONNECTING_TO_STEAM)))
                             .Add(In(State.CONNECTING_TO_STEAM)
                                  .Entry(connect)
                                  .Add(On(Event.CONNECTED_TO_STEAM).Transit(State.OPENING))
                                  .Add(On(Event.DISCONNECTED_FROM_STEAM).Call(connect).Transit(State.CONNECTING_TO_STEAM)))
                             .Add(In(State.OPENING)
                                  .Entry(open)
                                  .Add(On(Event.PLAYING_STATE_OPENED).Transit(State.CONNECTING)))
                             .Add(In(State.CONNECTING)
                                  .Entry(sayHello)
                                  .Add(On(Event.WELCOMED).Transit(State.GETTING_TICKET))
                                  .Add(On(Event.WELCOMED_STALE_LOBBY).Transit(State.IN_STALE_LOBBY)))
                             .Add(In(State.IN_STALE_LOBBY)
                                  .Entry(leaveLobby)
                                  .Add(On(Event.LEFT_LOBBY).Transit(State.GETTING_TICKET)))
                             .Add(In(State.GETTING_TICKET)
                                  .Entry(getTicket)
                                  .Add(On(Event.GOT_APP_TICKET).Transit(State.DOTA_HOME)))
                             .Add(In(State.DOTA_HOME)
                                  .Entry(createLobby)
                                  .Add(On(Event.CREATED_LOBBY).Transit(State.IN_LOBBY)))
                             .Add(In(State.IN_LOBBY)
                                  .Entry(joinRadiant)
                                  .Add(On(Event.LOBBY_READY).Transit(State.LOBBY_STARTING)))
                             .Add(In(State.LOBBY_STARTING)
                                  .Entry(startLobby)
                                  .Add(On(Event.SERVER_RUNNING).Transit(State.GETTING_AUTH)))
                             .Add(In(State.GETTING_AUTH)
                                  .Entry(getAuth)
                                  .Add(On(Event.GOT_AUTH).Transit(State.GETTING_SESSION)))
                             .Add(In(State.GETTING_SESSION)
                                  .Entry(beginSession)
                                  .Add(On(Event.GOT_SESSION).Transit(State.JOINING_GAME)))
                             .Add(In(State.JOINING_GAME)
                                  .Entry(join))
                             .Build();

            return(new BufferedMachine <Event, State>(unbuffered));
        }
Пример #3
0
 public MachineStateBinding <E, S> Exit(Machines.Call exit)
 {
     this.exit = exit;
     return(this);
 }
Пример #4
0
 public MachineStateBinding <E, S> Entry(Machines.Call enter)
 {
     this.enter = enter;
     return(this);
 }
Пример #5
0
 public MachineTransitionBinding <E, S> Call(Machines.Call call)
 {
     this.call = call;
     return(this);
 }
Пример #6
0
 public MachineTransitionBinding(E e)
 {
     this.e     = e;
     this.call  = null;
     this.state = null;
 }
Пример #7
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);
            }
        }