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); }
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); }