diff --git a/PayCheckServerLib/Files/PartySessionConfiguration.json b/PayCheckServerLib/Files/PartySessionConfiguration.json new file mode 100644 index 0000000..e4b580f --- /dev/null +++ b/PayCheckServerLib/Files/PartySessionConfiguration.json @@ -0,0 +1,49 @@ +{ + "PSNBaseURL": "https://s2s.np.playstation.net", + "autoJoin": false, + "clientVersion": "0", + "deployment": "", + "dsSource": "", + "fallbackClaimKeys": [], + "inactiveTimeout": 300, + "inviteTimeout": 60, + "joinability": "INVITE_ONLY", + "maxPlayers": 4, + "minPlayers": 1, + "name": "PartySession", + "nativeSessionSetting": { + "PSNServiceLabel": 0, + "PSNSupportedPlatforms": [], + "SessionTitle": "PAYDAY 3 Party", + "ShouldSync": true, + "XboxServiceConfigID": "00000000-0000-0000-0000-00006056e5d6", + "XboxSessionTemplateName": "Payday3", + "localizedSessionName": { + "defaultLanguage": "en-US", + "localizedText": { + "de-DE": "GRUPPE PAYDAY 3", + "en-US": "PAYDAY 3 Party", + "es-419": "GRUPO PAYDAY 3", + "es-ES": "GRUPO PAYDAY 3", + "fr-FR": "GROUPE PAYDAY 3", + "it-IT": "SQUADRA PAYDAY 3", + "ja-JP": "PAYDAY 3 パーティー", + "ko-KR": "PAYDAY 3 파티", + "pl-PL": "ZESPÓŁ PAYDAY 3", + "pt-BR": "GRUPO PAYDAY 3", + "ru-RU": "КОМАНДА PAYDAY 3", + "tr-TR": "PAYDAY 3 GRUP", + "zh-Hans": "PAYDAY 3 参加者", + "zh-Hant": "PAYDAY 3 隊伍" + } + } + }, + "persistent": false, + "preferredClaimKeys": [], + "requestedRegions": [ + "eu-central-1" + ], + "textChat": true, + "tieTeamsSessionLifetime": false, + "type": "NONE" +} \ No newline at end of file diff --git a/PayCheckServerLib/Helpers/PartyController.cs b/PayCheckServerLib/Helpers/PartyController.cs new file mode 100644 index 0000000..8485644 --- /dev/null +++ b/PayCheckServerLib/Helpers/PartyController.cs @@ -0,0 +1,161 @@ +using Newtonsoft.Json; +using PayCheckServerLib.Jsons; +using PayCheckServerLib.Jsons.PartyStuff; +using System.Security.Cryptography; + +namespace PayCheckServerLib.Helpers +{ + public class PartyController + { + + public class SavedStuff + { + public Dictionary Attributes; //WHY I NEED TO SAVE THIS AAAAAAAAAAAAAAA + public string Code; + public string CreatedBy; + public string Id; + public string LeaderId; + public long version; + public List Members; + public bool IsActive; + public bool IsFull; + public string SessionType; + public string CreatedAt; + public string UpdatedAt; + } + + public static Dictionary PartySaves = new(); + + public static PartyPost.Response ParsePartyToRSP(SavedStuff stuff) + { + PartyPost.Response rsp = new(); + rsp.Code = stuff.Code; + rsp.Attributes = stuff.Attributes; + rsp.Configuration = JsonConvert.DeserializeObject(File.ReadAllText($"Files/{stuff.SessionType}Configuration.json")); + rsp.Id = stuff.Id; + rsp.IsActive = stuff.IsActive; + rsp.IsFull = stuff.IsFull; + rsp.LeaderId = stuff.LeaderId; + rsp.CreatedBy = stuff.CreatedBy; + rsp.Namespace = "pd3"; + rsp.Version = stuff.version; + rsp.CreatedAt = stuff.CreatedAt; + rsp.UpdatedAt = stuff.UpdatedAt; + rsp.Members = stuff.Members; + return rsp; + } + + + public static PartyPost.Response CreateParty(PartyPostReq partyPost) + { + var code = UserIdHelper.CreateCode(); + + PartyPost.Response rsp = new(); + rsp.Code = code; + rsp.Attributes = partyPost.Attributes; + rsp.Configuration = JsonConvert.DeserializeObject(File.ReadAllText($"Files/{partyPost.ConfigurationName}Configuration.json")); + rsp.Id = UserIdHelper.CreateNewID(); + rsp.IsActive = true; + rsp.IsFull = false; + rsp.LeaderId = partyPost.Members[0].ID; + rsp.CreatedBy = partyPost.Members[0].ID; + rsp.Namespace = "pd3"; + rsp.Version = 1; //init version 1 + rsp.CreatedAt = DateTime.UtcNow.ToString("o"); + rsp.UpdatedAt = DateTime.UtcNow.ToString("o"); + rsp.Members = new(); + foreach (var item in partyPost.Members) + { + rsp.Members.Add(new() + { + Id = item.ID, + PlatformId = item.PlatformId.ToUpper(), + PlatformUserId = item.PlatformUserId, + Status = "JOINED", + StatusV2 = "JOINED", + UpdatedAt = DateTime.UtcNow.ToString("o") + }); + } + + SavedStuff saved = new() + { + Code = code, + SessionType = partyPost.ConfigurationName, + CreatedAt = rsp.CreatedAt, + CreatedBy = rsp.CreatedBy, + Id = rsp.Id, + IsActive = rsp.IsActive, + IsFull = rsp.IsFull, + LeaderId = rsp.LeaderId, + Members = rsp.Members, + UpdatedAt = rsp.UpdatedAt, + version = rsp.Version + }; + PartySaves.Add(code, saved); + Debugger.PrintInfo("New Party made!"); + return rsp; + } + + + public static PartyPost.Response JoinParty(string Code, TokenHelper.Token token) + { + if (!PartySaves.ContainsKey(Code)) + { + Debugger.PrintError("NO Code???? WHAT THE FUCK"); + throw new Exception("Code is not exist in saved parties????"); + } + var stuff = PartySaves[Code]; + stuff.UpdatedAt = DateTime.UtcNow.ToString("o"); + var user = stuff.Members.Where(x => x.Id == token.UserId).First(); + //shinenigans too edit user in members + stuff.Members.Remove(user); + user.Status = "JOINED"; + user.StatusV2 = "JOINED"; + user.UpdatedAt = DateTime.UtcNow.ToString("o"); + stuff.Members.Add(user); + //stuff.version += 1; //does this needed? + return ParsePartyToRSP(stuff); + } + + + + public static PartyPost.Response UpdateParty(string PartyId, dynamic body) + { + var party = PartySaves.Where(x=>x.Value.Id == PartyId).FirstOrDefault().Value; + if (party == null) + { + Debugger.PrintError("NO Code???? WHAT THE FUCK"); + throw new Exception("Code is not exist in saved parties????"); + } + + party.UpdatedAt = DateTime.UtcNow.ToString("o"); + party.Attributes = body.attributes; + party.version = body.version + 1; + + return ParsePartyToRSP(party); + } + + public static void LeftParty(string PartyId, string UserId, PC3Server.PC3Session session) + { + var party = PartySaves.Where(x => x.Value.Id == PartyId).FirstOrDefault().Value; + if (party == null) + { + Debugger.PrintError("NO Code???? WHAT THE FUCK"); + throw new Exception("Code is not exist in saved parties????"); + } + + party.UpdatedAt = DateTime.UtcNow.ToString("o"); + party.version += 1; + foreach (var m in party.Members) + { + if (m.Id == UserId) + { + m.Status = "LEFT"; + m.StatusV2 = "LEFT"; + } + } + //todo send other users update that we left! + //or if we are the leader send this one dead and sent to leave everybody + } + } +} diff --git a/PayCheckServerLib/Helpers/TokenHelper.cs b/PayCheckServerLib/Helpers/TokenHelper.cs index 37e2b1c..dbdb665 100644 --- a/PayCheckServerLib/Helpers/TokenHelper.cs +++ b/PayCheckServerLib/Helpers/TokenHelper.cs @@ -18,7 +18,12 @@ public enum TokenPlatform { Unknow, Steam, - Device + Device, + EOS, + EpicGames, + PS4, + PS5, + XBOX } public static Token GetTokenFromPlatform(string platformId, TokenPlatform platformType) diff --git a/PayCheckServerLib/Helpers/UserIdHelper.cs b/PayCheckServerLib/Helpers/UserIdHelper.cs index 6cbc8b1..59f3d96 100644 --- a/PayCheckServerLib/Helpers/UserIdHelper.cs +++ b/PayCheckServerLib/Helpers/UserIdHelper.cs @@ -29,6 +29,22 @@ public static string CreateNewID() return md5_str; } + public static string CreateCode() + { + Random rand = new(); + int stringlen = 7; + int randValue; + string str = ""; + char letter; + for (int i = 0; i < stringlen; i++) + { + randValue = rand.Next(0, 26); + letter = Convert.ToChar(randValue + 65); + str = str + letter; + } + return str; + } + /// /// Creating String from MD5 /// diff --git a/PayCheckServerLib/Jsons/PartyStuff/OnPartyCreated.cs b/PayCheckServerLib/Jsons/PartyStuff/OnPartyCreated.cs new file mode 100644 index 0000000..ce61a02 --- /dev/null +++ b/PayCheckServerLib/Jsons/PartyStuff/OnPartyCreated.cs @@ -0,0 +1,19 @@ +using Newtonsoft.Json; + +namespace PayCheckServerLib.Jsons.PartyStuff +{ + public class OnPartyCreated + { + [JsonProperty("CreatedBy")] + public string CreatedBy { get; set; } + + [JsonProperty("PartyID")] + public string PartyId { get; set; } + + [JsonProperty("TextChat")] + public bool TextChat { get; set; } + + [JsonProperty("Code")] + public string Code { get; set; } + } +} diff --git a/PayCheckServerLib/Jsons/PartyStuff/OnPartyUpdated.cs b/PayCheckServerLib/Jsons/PartyStuff/OnPartyUpdated.cs new file mode 100644 index 0000000..faffcd7 --- /dev/null +++ b/PayCheckServerLib/Jsons/PartyStuff/OnPartyUpdated.cs @@ -0,0 +1,76 @@ +using Newtonsoft.Json; + +namespace PayCheckServerLib.Jsons.PartyStuff +{ + internal class OnPartyUpdated + { + [JsonProperty("ID")] + public string Id { get; set; } + + [JsonProperty("Namespace")] + public string Namespace { get; set; } + + [JsonProperty("Members")] + public List Members { get; set; } + + [JsonProperty("Attributes")] + public Dictionary Attributes { get; set; } + + [JsonProperty("CreatedAt")] + public string CreatedAt { get; set; } + + [JsonProperty("CreatedBy")] + public string CreatedBy { get; set; } + + [JsonProperty("UpdatedAt")] + public string UpdatedAt { get; set; } + + [JsonProperty("Version")] + public long Version { get; set; } + + [JsonProperty("Configuration")] + public Configuration Configuration { get; set; } + + [JsonProperty("ConfigurationName")] + public string ConfigurationName { get; set; } + + [JsonProperty("IsFull")] + public bool IsFull { get; set; } + + [JsonProperty("LeaderID")] + public string LeaderId { get; set; } + + [JsonProperty("Code")] + public string Code { get; set; } + } + + public partial class Configuration + { + [JsonProperty("Name")] + public string Name { get; set; } + + [JsonProperty("Joinability")] + public string Joinability { get; set; } + + [JsonProperty("MinPlayers")] + public long MinPlayers { get; set; } + + [JsonProperty("MaxPlayers")] + public long MaxPlayers { get; set; } + + [JsonProperty("ClientVersion")] + public string ClientVersion { get; set; } + + [JsonProperty("RequestedRegions")] + public List RequestedRegions { get; set; } + + [JsonProperty("Type")] + public string Type { get; set; } + + [JsonProperty("InviteTimeout")] + public long InviteTimeout { get; set; } + + [JsonProperty("InactiveTimeout")] + public long InactiveTimeout { get; set; } + } +} diff --git a/PayCheckServerLib/Jsons/PartyStuff/PartyPost.cs b/PayCheckServerLib/Jsons/PartyStuff/PartyPost.cs index d18c79c..abde089 100644 --- a/PayCheckServerLib/Jsons/PartyStuff/PartyPost.cs +++ b/PayCheckServerLib/Jsons/PartyStuff/PartyPost.cs @@ -4,7 +4,7 @@ namespace PayCheckServerLib.Jsons.PartyStuff { public class PartyPost { - public partial class Basic + public partial class Response { [JsonProperty("attributes")] public Dictionary Attributes { get; set; } diff --git a/PayCheckServerLib/Jsons/PartyStuff/PartyPostReq.cs b/PayCheckServerLib/Jsons/PartyStuff/PartyPostReq.cs index a170734..1bc4945 100644 --- a/PayCheckServerLib/Jsons/PartyStuff/PartyPostReq.cs +++ b/PayCheckServerLib/Jsons/PartyStuff/PartyPostReq.cs @@ -4,20 +4,17 @@ namespace PayCheckServerLib.Jsons.PartyStuff { public class PartyPostReq { - public partial class Basic - { - [JsonProperty("members")] - public List Members { get; set; } + [JsonProperty("members")] + public List Members { get; set; } - [JsonProperty("attributes")] - public Dictionary Attributes { get; set; } + [JsonProperty("attributes")] + public Dictionary Attributes { get; set; } - [JsonProperty("configurationName")] - public string ConfigurationName { get; set; } + [JsonProperty("configurationName")] + public string ConfigurationName { get; set; } - [JsonProperty("textChat")] - public bool TextChat { get; set; } - } + [JsonProperty("textChat")] + public bool TextChat { get; set; } public partial class Member { diff --git a/PayCheckServerLib/PayCheckServerLib.csproj b/PayCheckServerLib/PayCheckServerLib.csproj index 0b60fcb..75fc53e 100644 --- a/PayCheckServerLib/PayCheckServerLib.csproj +++ b/PayCheckServerLib/PayCheckServerLib.csproj @@ -22,6 +22,7 @@ + diff --git a/PayCheckServerLib/Responses/Parties.cs b/PayCheckServerLib/Responses/Parties.cs index 96cc112..66f5503 100644 --- a/PayCheckServerLib/Responses/Parties.cs +++ b/PayCheckServerLib/Responses/Parties.cs @@ -1,33 +1,104 @@ using NetCoreServer; using Newtonsoft.Json; -using static PayCheckServerLib.Responses.MatchTickets; +using PayCheckServerLib.Helpers; +using PayCheckServerLib.Jsons.PartyStuff; +using PayCheckServerLib.WSController; namespace PayCheckServerLib.Responses { public class Parties { + [HTTP("POST", "/session/v1/public/namespaces/pd3/party")] + public static bool Party(HttpRequest request, PC3Server.PC3Session session) + { + var body = JsonConvert.DeserializeObject(request.Body); + var rsp = PartyController.CreateParty(body); + ResponseCreator response = new(); + response.SetBody(JsonConvert.SerializeObject(rsp)); + session.SendResponse(response.GetResponse()); + + //send notif to user to party created + var wss_sess = session.GetWSLobby(session.WSUserId); + Dictionary resp = new() + { + { "type", "messageSessionNotif" }, + { "topic", "OnPartyCreated" }, + { "sentAt", DateTime.UtcNow.ToString("o") }, + }; + OnPartyCreated pld = new() + { + Code = rsp.Code, + CreatedBy = rsp.CreatedBy, + PartyId = rsp.Id, + TextChat = body.TextChat + }; + resp.Add("payload", LobbyControl.Base64Encode(JsonConvert.SerializeObject(pld))); + LobbyControl.SendToLobby(resp,wss_sess); + return true; + } [HTTP("PATCH", "/session/v1/public/namespaces/pd3/parties/{partyid}")] public static bool PATCH_Parties(HttpRequest request, PC3Server.PC3Session session) { - /* - var body = JsonConvert.DeserializeObject(request.Body); + var body = JsonConvert.DeserializeObject(request.Body); + PartyPost.Response rsp = PartyController.UpdateParty(session.HttpParam["partyid"],body); ResponseCreator response = new(); - response.SetBody(JsonConvert.SerializeObject("")); + response.SetBody(JsonConvert.SerializeObject(rsp)); session.SendResponse(response.GetResponse()); - */ - return false; + + Dictionary resp = new() + { + { "type", "messageSessionNotif" }, + { "topic", "OnPartyUpdated" }, + { "sentAt", DateTime.UtcNow.ToString("o") }, + }; + OnPartyUpdated pld = new() + { + Code = rsp.Code, + CreatedBy = rsp.CreatedBy, + Attributes = rsp.Attributes, + Configuration = new() + { + ClientVersion = rsp.Configuration.ClientVersion, + Joinability = rsp.Configuration.Joinability, + InactiveTimeout = rsp.Configuration.InactiveTimeout, + InviteTimeout = rsp.Configuration.InviteTimeout, + MaxPlayers = rsp.Configuration.MaxPlayers, + MinPlayers = rsp.Configuration.MinPlayers, + Name = rsp.Configuration.Name, + Type = rsp.Configuration.Type, + RequestedRegions = rsp.Configuration.RequestedRegions + }, + ConfigurationName = rsp.Configuration.Name, + CreatedAt = rsp.CreatedAt, + Id = rsp.Id, + IsFull = rsp.IsFull, + LeaderId = rsp.LeaderId, + Members = rsp.Members, + Namespace = "pd3", + UpdatedAt = rsp.UpdatedAt, + Version = rsp.Version + }; + resp.Add("payload", LobbyControl.Base64Encode(JsonConvert.SerializeObject(pld))); + + List ids = new(); + rsp.Members.ForEach(m => ids.Add(m.Id)); + + foreach (var id in session.WSSServer().WSUserIds) + { + if (ids.Contains(id)) + { + LobbyControl.SendToLobby(resp, session.GetWSLobby(id)); + } + } + return true; } [HTTP("DELETE", "/session/v1/public/namespaces/pd3/parties/{partyid}/users/me/leave")] public static bool LeaveParties(HttpRequest request, PC3Server.PC3Session session) { - /* - var body = JsonConvert.DeserializeObject(request.Body); - ResponseCreator response = new(); - response.SetBody(JsonConvert.SerializeObject("")); + ResponseCreator response = new(204); session.SendResponse(response.GetResponse()); - */ return false; } diff --git a/PayCheckServerLib/WSController/LobbyControl.cs b/PayCheckServerLib/WSController/LobbyControl.cs index e2328e5..3fa5c4f 100644 --- a/PayCheckServerLib/WSController/LobbyControl.cs +++ b/PayCheckServerLib/WSController/LobbyControl.cs @@ -8,6 +8,11 @@ namespace PayCheckServerLib.WSController { public class LobbyControl { + public static string Base64Encode(string plainText) + { + var plainTextBytes = Encoding.UTF8.GetBytes(plainText); + return Convert.ToBase64String(plainTextBytes); + } public static void Control(byte[] buffer, long offset, long size, PC3Session session) { if (size == 0)