Esempio n. 1
0
        public async Task <SkateStatsResponse> Handle(SkateStatsRequest request, CancellationToken cancellationToken)
        {
            var response = new SkateStatsResponse();

            await _notificationHandler.EnqueueNotification(new SkateStatsReportNotification
            {
                Error         = 0,
                Final         = false,
                Grid          = 0,   //always 0
                RequestReport = new RequestReport
                {                    //TODO: figure out what these do
                    Finished    = true,
                    Grid        = 0, //always 0
                    GameType    = 1,
                    Prcs        = false,
                    StatsReport = request.StatsReport
                }
            });

            return(response);
        }
Esempio n. 2
0
        public async Task <CreateGameResponse> Handle(CreateGameRequest request, CancellationToken cancellationToken)
        {
            if (_clientContext.UserSessionId == null)
            {
                throw new Exception("UserSessionId not on context");
            }
            var currentSession = _userSessionManager.GetSession(_clientContext.UserSessionId.Value);

            ushort capacity = 6;                                 //TODO: hardcoded capacity
            var    game     = _gameManager.CreateGame(capacity); //TODO pass game instead of returning it?

            game.Name        = request.GameName;
            game.Settings    = request.GameSettings;
            game.Attributes  = request.Attributes;
            game.Version     = request.VersionString;
            game.AdminId     = currentSession.UserId; //TODO: make sure this is the right id
            game.HostId      = currentSession.UserId; //TODO: make sure this is the right id
            game.HostNetwork = currentSession.NetworkAddress;

            _gameManager.AddPlayer(game.GameId, new Player
            {
                AccountId      = currentSession.AccountId,
                UserId         = currentSession.UserId,
                PersonaId      = currentSession.PersonaId,
                Username       = currentSession.Username,
                ExternalId     = currentSession.ExternalId,
                ExternalBlob   = currentSession.ExternalBlob,
                State          = PlayerState.Connected,
                ConnectTime    = DateTimeOffset.Now.ToUnixTimeMilliseconds() * 1000, //microseconds
                NetworkAddress = currentSession.NetworkAddress,
            });

            var response = new CreateGameResponse
            {
                GameId = game.GameId
            };

            var players = new List <PlayerData>();

            foreach (var player in game.Players)
            {
                if (player == null)
                {
                    continue;                 //empty slot
                }
                players.Add(new PlayerData
                {
                    Blob             = null,
                    ExternalId       = player.ExternalId,
                    Gid              = game.GameId,
                    Locale           = 1701729619, //enUS
                    Username         = player.Username,
                    NetworkData      = new QosNetworkData(),
                    PlayerAttributes = new Dictionary <string, string>
                    {
                        { "dlc_mask", "483" } //matches start matchmaking MASK?
                    },
                    PersonaId     = player.PersonaId,
                    PlayerNetwork = new KeyValuePair <NetworkAddressType, PairNetworkAddress>(NetworkAddressType.Pair, player.NetworkAddress),
                    Sid           = player.SlotId,
                    Slot          = 0,
                    PlayerState   = player.State,
                    Team          = 65535,
                    Tidx          = 65535,
                    Time          = player.ConnectTime,
                    UserId        = player.UserId
                });
            }

            await _notificationHandler.EnqueueNotification(new GameSetupNotification
            {
                Error    = 0,
                GameData = new GameData
                {
                    Admins = new List <uint> {
                        game.AdminId
                    },
                    Attributes = game.Attributes,
                    Cap        = new List <ushort> {
                        capacity, 0
                    },
                    GameId       = game.GameId,
                    GameName     = game.Name,
                    Gpvh         = 1, //TODO hardcoded value?
                    GameSettings = game.Settings,
                    Gsid         = 1, //normally random but not used anywhere
                    GameState    = game.State,
                    Gver         = 1,
                    HostNetwork  = new List <KeyValuePair <NetworkAddressType, PairNetworkAddress> >
                    {
                        new KeyValuePair <NetworkAddressType, PairNetworkAddress>(NetworkAddressType.Pair, game.HostNetwork)
                    },
                    Hses   = 1234567, //TODO
                    Ignore = false,
                    Matr   = null,
                    //Matr = new Dictionary<string, string> //TODO sent on not host
                    //{
                    //    {"tprt", "0"},
                    //    {"vprt", "9041"} //TODO? voice port?
                    //},
                    Mcap            = capacity, //TODO: also can be 30?
                    NetworkData     = new QosNetworkData(),
                    NetworkTopology = NetworkTopology.PeerToPeerFullMesh,
                    Pgid            = Guid.NewGuid().ToString(),
                    Pgsr            = null,
                    PlatformHost    = new HostData
                    {
                        HostPersonaId = game.HostId,
                        HostSlot      = 0
                    },
                    PingServerName = "",
                    QueueCapacity  = 0,
                    Seed           = 12345678, //TODO: random?
                    TopologyHost   = new HostData
                    {
                        HostPersonaId = game.HostId,
                        HostSlot      = 0
                    },
                    Uuid          = game.Uuid,
                    VoipTopology  = VoipTopology.PeerToPeer,
                    VersionString = game.Version,
                    Xnnc          = null,
                    Xses          = null
                },
                MatchmakingId = 1234, //TODO: pull from matchmakingmanager //same as start matchmaking
                Players       = players
            });

            return(response);
        }
        public async Task <StartMatchmakingResponse> Handle(StartMatchmakingRequest request, CancellationToken cancellationToken)
        {
            if (_clientContext.UserSessionId == null)
            {
                throw new Exception("UserSessionId not on context");
            }
            var currentSession = _userSessionManager.GetSession(_clientContext.UserSessionId.Value);

            //uint matchmakingId = _matchmakingManager.CreateMatchmakingSession();
            uint matchmakingId = 1234;
            var  response      = new StartMatchmakingResponse
            {
                MatchmakingSessionId = matchmakingId
            };

            //TODO async
            await _notificationHandler.EnqueueNotification(new MatchmakingStatusNotification
            {
                Asil = new List <AsilData>
                {
                    new AsilData
                    {
                        Cgs = new CgsData
                        {
                            Evst = 0,
                            Mmsn = 0,
                            Nomp = 0
                        },
                        Cust = new CustData
                        {
                            Exps = new ExpsData
                            {
                                Mask = 483 //TODO dlc mask?
                            }
                        },
                        Dnfs = new DnfsData
                        {
                            Mdnf = 0,  //TODO
                            Xdnf = 101 //TODO
                        },
                        Fgs = new FgsData
                        {
                            Gnum = 13 //TODO
                        },
                        Geos = new GeosData
                        {
                            Dist = 0
                        },
                        Grda = new Dictionary <string, GrdaData>  //TODO should match attrs
                        {
                            { "difficultyModeRule", new GrdaData
                              {
                                  Name   = "difficultyModeRule",
                                  Values = new List <string> {
                                      "1"
                                  }
                              } },//TODO: fill in rest here
                        },
                        Gsrd = new GsrdData
                        {
                            Pmax = 6,
                            Pmin = 1 //TODO: should be 2
                        },
                        Hbrd = new HbrdData
                        {
                            Bval = 1 //TODO
                        },
                        Hvrd = new HvrdData
                        {
                            Vval = 1 //TODO
                        },
                        PingServerNames = new PingServerNames
                        {
                            Values = new List <string> {
                                _blazeConfig.QosName
                            }                                                  //qos servers
                        },
                        Rrda = new RrdaData
                        {
                            Rval = 13
                        },
                        Tsrs = new TsrsData(),
                    }
                },
                MatchmakingSessionId = matchmakingId,
                UserSessionId        = currentSession.SessionId
            });

            //TODO: matchmaking manager?
            var game = _gameManager.FindGame(games => games.FirstOrDefault());

            if (game == null) //No game exists go ahead and force a new one
            {
                await _notificationHandler.EnqueueNotification(new MatchmakingFinishedNotification
                {
                    Fit    = 0,
                    GameId = 0,
                    Maxf   = 0,
                    MatchmakingSessionId = matchmakingId,
                    Result        = MatchmakingResult.TimedOut, //TimeOut will result in GameManager 0x19 message
                    UserSessionId = currentSession.SessionId
                });

                return(response);
            }

            //Join existing game
            await _notificationHandler.EnqueueNotification(new MatchmakingFinishedNotification
            {
                Fit    = 100,                                         //TODO: what value?
                GameId = game.GameId,
                Maxf   = 100,                                         //TODO: what value?
                MatchmakingSessionId = matchmakingId,
                Result        = MatchmakingResult.JoinedExistingGame, //TODO: I think this value is correct
                UserSessionId = currentSession.SessionId
            });


            //Tell the new user about all players and the game
            foreach (var player in game.Players)
            {
                if (player == null)
                {
                    continue;                 //empty slot
                }
                await _notificationHandler.SendNotification(new UserAddedNotification
                {
                    AccountId     = player.AccountId,
                    AccountLocale = 1701729619, //enUS
                    ExternalBlob  = player.ExternalBlob,
                    ExternalId    = player.ExternalId,
                    Id            = player.UserId,
                    Username      = player.Username,
                    Online        = true,
                    PersonaId     = player.PersonaId
                });

                await _notificationHandler.SendNotification(new UserExtendedDataNotification
                {
                    UserId = player.UserId,
                    Data   = new ExtendedData
                    {
                        Address        = new KeyValuePair <NetworkAddressType, NetworkAddress>(NetworkAddressType.Pair, player.NetworkAddress),
                        PingServerName = _blazeConfig.QosName,         //TODO dont hardcode
                        Cty            = "",
                        DataMap        = new Dictionary <uint, int>(), //TODO: this is missing from the real response
                        HardwareFlags  = 0,
                        Pings          = new List <int> {
                            10
                        },                               //TODO: dont harcode
                        NetworkData = new QosNetworkData //TODO: dont hardcode
                        {
                            DownstreamBitsPerSecond = 100000,
                            NatType = NatType.Open,
                            UpstreamBitsPerSecond = 100000
                        },
                        UserAttributes = 0,
                        UserGameList   = new List <ulong> {
                            ((ulong)0x4 << 48 | (ulong)0x1 << 32 | game.GameId)
                        }                                                                                     //gross
                    }
                });
            }

            _gameManager.AddPlayer(game.GameId, new Player
            {
                AccountId      = currentSession.AccountId,
                UserId         = currentSession.UserId,
                PersonaId      = currentSession.PersonaId,
                Username       = currentSession.Username,
                ExternalId     = currentSession.ExternalId,
                ExternalBlob   = currentSession.ExternalBlob,
                State          = PlayerState.Connecting,
                ConnectTime    = DateTimeOffset.Now.ToUnixTimeMilliseconds() * 1000, //microseconds
                NetworkAddress = currentSession.NetworkAddress,
            });

            var currentUserAdded = new UserAddedNotification
            {
                AccountId     = currentSession.AccountId,
                AccountLocale = 1701729619, //enUS
                ExternalBlob  = currentSession.ExternalBlob,
                ExternalId    = currentSession.ExternalId,
                Id            = currentSession.UserId,
                Username      = currentSession.Username,
                Online        = true,
                PersonaId     = currentSession.PersonaId
            };

            var currentUserExtended = new UserExtendedDataNotification
            {
                UserId = currentSession.UserId,
                Data   = new ExtendedData
                {
                    Address = new KeyValuePair <NetworkAddressType, NetworkAddress>(NetworkAddressType.Pair,
                                                                                    currentSession.NetworkAddress),
                    PingServerName = _blazeConfig.QosName,         //TODO dont hardcode
                    Cty            = "",
                    DataMap        = new Dictionary <uint, int>(), //TODO: this is missing from the real response
                    HardwareFlags  = 0,
                    Pings          = new List <int> {
                        10
                    },                               //TODO: dont harcode
                    NetworkData = new QosNetworkData //TODO: dont hardcode
                    {
                        DownstreamBitsPerSecond = 100000,
                        NatType = NatType.Open,
                        UpstreamBitsPerSecond = 100000
                    },
                    UserAttributes = 0,
                    UserGameList   = new List <ulong> {
                        ((ulong)0x4 << 48 | (ulong)0x1 << 32 | game.GameId)
                    }                                                                                      //gross
                }
            };

            var players = new List <PlayerData>();

            foreach (var player in game.Players)
            {
                if (player == null)
                {
                    continue;                 //empty slot
                }
                await _notificationHandler.SendNotification(player.UserId, currentUserExtended);

                await _notificationHandler.SendNotification(player.UserId, currentUserAdded);

                players.Add(new PlayerData
                {
                    Blob             = null,
                    ExternalId       = player.ExternalId,
                    Gid              = game.GameId,
                    Locale           = 1701729619, //enUS
                    Username         = player.Username,
                    NetworkData      = new QosNetworkData(),
                    PlayerAttributes = new Dictionary <string, string>
                    {
                        { "dlc_mask", "483" } //matches start matchmaking MASK?
                    },
                    PersonaId     = player.UserId, //TODO should be PlayerId?
                    PlayerNetwork = new KeyValuePair <NetworkAddressType, PairNetworkAddress>(NetworkAddressType.Pair, player.NetworkAddress),
                    Sid           = player.SlotId,
                    Slot          = 0,
                    PlayerState   = player.State,
                    Team          = 65535,
                    Tidx          = 65535,
                    Time          = player.ConnectTime,
                    UserId        = player.UserId
                });
            }

            //Tell new player about the game
            await _notificationHandler.EnqueueNotification(new GameSetupNotification
            {
                Error    = 0,
                GameData = new GameData
                {
                    Admins = new List <uint> {
                        game.AdminId
                    },
                    Attributes = game.Attributes,
                    Cap        = new List <ushort> {
                        game.Capacity, 0
                    },
                    GameId       = game.GameId,
                    GameName     = game.Name,
                    Gpvh         = 1, //TODO hardcoded value?
                    GameSettings = game.Settings,
                    Gsid         = 1, //normally random but not used anywhere
                    GameState    = game.State,
                    Gver         = 1,
                    HostNetwork  = new List <KeyValuePair <NetworkAddressType, PairNetworkAddress> >
                    {
                        new KeyValuePair <NetworkAddressType, PairNetworkAddress>(NetworkAddressType.Pair, game.HostNetwork)
                    },
                    Hses   = 1234567, //TODO host session Id?
                    Ignore = false,
                    Matr   = new Dictionary <string, string>
                    {
                        { "tprt", "0" },
                        { "vprt", "0" } //TODO? voice port?
                    },
                    Mcap            = game.Capacity, //6 or 30?
                    NetworkData     = new QosNetworkData(),
                    NetworkTopology = NetworkTopology.PeerToPeerFullMesh,
                    Pgid            = "",
                    Pgsr            = null,
                    PlatformHost    = new HostData
                    {
                        HostPersonaId = game.HostId,
                        HostSlot      = 0
                    },
                    PingServerName = "",
                    QueueCapacity  = 0,
                    Seed           = 12345678, //TODO: random?
                    TopologyHost   = new HostData
                    {
                        HostPersonaId = game.HostId,
                        HostSlot      = 0
                    },
                    Uuid          = game.Uuid,
                    VoipTopology  = VoipTopology.PeerToPeer,
                    VersionString = game.Version,
                    Xnnc          = null,
                    Xses          = null
                },
                MatchmakingId = matchmakingId, //same as start matchmaking
                Players       = players
            });

            return(response);
        }
        public async Task <LoginResponse> Handle(LoginRequest request, CancellationToken cancellationToken)
        {
            Logger.Debug($"LOGIN for {_clientContext.ConnectionId}");

            var ticket = _ticketDecoder.DecodeTicket(request.Ticket);

            if (ticket == null)
            {
                throw new Exception("Could not parse ticket, unable to login");
            }

            var persona = await _context.Personas.SingleOrDefaultAsync(x => x.ExternalId == ticket.Body.UserId, cancellationToken : cancellationToken);

            //First time we have seen this persona
            if (persona == null)
            {
                //TODO: a hack, this normally comes from the auth new login flow but I dont want to prompt for a login
                var externalBlob = new List <byte>();
                externalBlob.AddRange(Encoding.ASCII.GetBytes(ticket.Body.Username.PadRight(20, '\0')));
                externalBlob.AddRange(Encoding.ASCII.GetBytes(ticket.Body.Domain));
                externalBlob.AddRange(Encoding.ASCII.GetBytes(ticket.Body.Region));
                externalBlob.AddRange(Encoding.ASCII.GetBytes("ps3"));
                externalBlob.Add(0x0);
                externalBlob.Add(0x1);
                externalBlob.AddRange(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });

                //Create new user
                var user = new User();
                await _context.Users.AddAsync(user, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);

                //For now just use the blazeid for both AccountId (this is so the rest of the logic can use those values where they are supposed to)
                user.AccountId = user.Id;

                persona = new Persona
                {
                    ExternalId     = ticket.Body.UserId,
                    ExternalBlob   = externalBlob.ToArray(),
                    ExternalIdType = ticket.Body.IssuerId == 100 ? PersonaExternalIdType.PS3 : PersonaExternalIdType.Rpcs3, //100 is retail issuerId
                    Username       = ticket.Body.Username,
                    User           = user
                };
                await _context.Personas.AddAsync(persona, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);
            }

            //TODO: handle same user connecting/logging in at the same time

            //Create session
            var newSession = new UserSessionData
            {
                AccountId    = persona.User.AccountId,
                UserId       = persona.UserId,
                PersonaId    = persona.Id,
                Username     = persona.Username,
                ExternalId   = persona.ExternalId,
                ExternalBlob = persona.ExternalBlob,
            };
            var sessionData = _userSessionManager.StoreSession(newSession);

            //Update login time
            var currentTimestamp = TimeUtil.GetUnixTimestamp();

            persona.LastUsed       = currentTimestamp;
            persona.User.LastLogin = currentTimestamp;
            await _context.SaveChangesAsync(cancellationToken);

            _clientContext.UserId        = newSession.UserId;
            _clientContext.UserSessionId = sessionData.SessionId;

            var response = new LoginResponse
            {
                Agup    = false,
                Priv    = "",
                Session = new LoginSession
                {
                    BlazeId       = newSession.UserId,
                    FirstLogin    = false, //TODO
                    SessionKey    = sessionData.SessionKey,
                    LastLoginTime = currentTimestamp,
                    Email         = "",
                    Persona       = new LoginPersona
                    {
                        DisplayName    = newSession.Username,
                        LastUsed       = currentTimestamp,
                        PersonaId      = newSession.UserId,
                        ExternalId     = newSession.ExternalId,
                        ExternalIdType = ExternalIdType.PS3,
                    },
                    AccountId = newSession.AccountId,
                },
                Spam      = true, //TODO: what is spam?
                TermsHost = "",
                TermsUrl  = ""
            };

            await _notificationHandler.EnqueueNotification(persona.UserId, new UserAddedNotification
            {
                AccountId     = newSession.AccountId,
                AccountLocale = 1701729619, //enUS //TODO: not hardcode
                ExternalBlob  = newSession.ExternalBlob,
                Id            = newSession.UserId,
                PersonaId     = newSession.PersonaId,
                Username      = newSession.Username,
                ExternalId    = newSession.ExternalId,
                Online        = true
            });

            await _notificationHandler.EnqueueNotification(persona.UserId, new UserExtendedDataNotification
            {
                Data = new ExtendedData
                {
                    Address        = new KeyValuePair <NetworkAddressType, NetworkAddress>(NetworkAddressType.Unset, null),
                    PingServerName = "",
                    Cty            = "",
                    DataMap        = new Dictionary <uint, int>
                    {
                        { 0x00070047, 0 }
                    },
                    HardwareFlags = 0,
                    NetworkData   = new QosNetworkData
                    {
                        DownstreamBitsPerSecond = 0,
                        NatType = NatType.Open,
                        UpstreamBitsPerSecond = 0
                    },
                    UserAttributes = 0 //always 0
                },
                UserId = newSession.UserId
            });

            return(response);
        }