diff --git a/EpinelPS/Database/JsonDb.cs b/EpinelPS/Database/JsonDb.cs index 4ea0331..ef4af45 100644 --- a/EpinelPS/Database/JsonDb.cs +++ b/EpinelPS/Database/JsonDb.cs @@ -129,9 +129,9 @@ namespace EpinelPS.Database public string Nickname = "SomePlayer"; public int ProfileIconId = 39900; public bool ProfileIconIsPrism = false; - public int ProfileFrame = 1; + public int ProfileFrame = 25; public bool IsAdmin = false; - + public bool sickpulls = false; public bool IsBanned = false; public DateTime BanStart; public DateTime BanEnd; @@ -170,7 +170,7 @@ namespace EpinelPS.Database public List CompletedSideStoryStages = new(); public List Memorial = new(); - public List JukeboxBgm = new(); + public List JukeboxBgm = new List(); // Event data public Dictionary EventInfo = new(); @@ -442,5 +442,44 @@ namespace EpinelPS.Database File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + "/db.json", JsonConvert.SerializeObject(Instance, Formatting.Indented)); } } + public static int CurrentJukeboxBgm(int position) + { + var activeJukeboxBgm = new List(); + //important first position holds lobby bgm id and second commanders room bgm id + foreach (var user in Instance.Users) + { + if (user.JukeboxBgm == null || user.JukeboxBgm.Count == 0) + { + // this if statemet only exists becaus some weird black magic copies default value over and over + //in the file when its set in public List JukeboxBgm = new List(); + //delete when or if it gets fixed + + user.JukeboxBgm = new List { 2,5 }; + } + + activeJukeboxBgm.AddRange(user.JukeboxBgm); + } + + if (activeJukeboxBgm.Count == 0) + { + return 8995001; + } + + position = (position == 2 && activeJukeboxBgm.Count > 1) ? 2 : 1; + return activeJukeboxBgm[position - 1]; + } + + public static bool IsSickPulls(User selectedUser) + { + if (selectedUser != null) + { + return selectedUser.sickpulls; + } + else + { + throw new Exception($"User with ID {selectedUser.ID} not found"); + } + } + } } diff --git a/EpinelPS/GameData/GameData.cs b/EpinelPS/GameData/GameData.cs index aac841c..4426327 100644 --- a/EpinelPS/GameData/GameData.cs +++ b/EpinelPS/GameData/GameData.cs @@ -22,6 +22,7 @@ namespace EpinelPS.StaticInfo return _instance; } } + private ZipFile MainZip; private MemoryStream ZipStream; private Dictionary questDataRecords; @@ -30,16 +31,21 @@ namespace EpinelPS.StaticInfo private JArray userExpDataRecords; private Dictionary chapterCampaignData; private JArray characterCostumeTable; - private Dictionary characterTable; + public Dictionary characterTable; private Dictionary tutorialTable; private Dictionary itemEquipTable; - private Dictionary FieldMapData = []; - private Dictionary LevelData = []; - private Dictionary TacticAcademyLessons = []; - public Dictionary SidestoryRewardTable = []; - public Dictionary PositionReward = new Dictionary(); - public Dictionary FieldItems = []; - public Dictionary OutpostBattle = []; + private Dictionary FieldMapData = new Dictionary(); // Fixed initialization + private Dictionary LevelData = new Dictionary(); // Fixed initialization + private Dictionary TacticAcademyLessons = new Dictionary(); // Fixed initialization + public Dictionary SidestoryRewardTable = new Dictionary(); // Fixed initialization + public Dictionary PositionReward = new Dictionary(); // Fixed initialization + public Dictionary FieldItems = new Dictionary(); // Fixed initialization + public Dictionary OutpostBattle = new Dictionary(); // Fixed initialization + public Dictionary jukeboxListDataRecords; + private Dictionary jukeboxThemeDataRecords; + public Dictionary gachaTypes = new Dictionary(); // Fixed initialization + public Dictionary eventManagers = new Dictionary(); + public byte[] Sha256Hash; public int Size; @@ -74,6 +80,10 @@ namespace EpinelPS.StaticInfo tutorialTable = new(); itemEquipTable = new(); + // Initialize Jukebox data dictionaries + jukeboxListDataRecords = new Dictionary(); + jukeboxThemeDataRecords = new Dictionary(); + var rawBytes = File.ReadAllBytes(filePath); Sha256Hash = SHA256.HashData(rawBytes); Size = rawBytes.Length; @@ -81,6 +91,7 @@ namespace EpinelPS.StaticInfo LoadGameData(filePath); if (MainZip == null) throw new Exception("failed to read zip file"); } + #region Data loading private static byte[] PresharedValue = [0xCB, 0xC2, 0x1C, 0x6F, 0xF3, 0xF5, 0x07, 0xF5, 0x05, 0xBA, 0xCA, 0xD4, 0x98, 0x28, 0x84, 0x1F, 0xF0, 0xD1, 0x38, 0xC7, 0x61, 0xDF, 0xD6, 0xE6, 0x64, 0x9A, 0x85, 0x13, 0x3E, 0x1A, 0x6A, 0x0C, 0x68, 0x0E, 0x2B, 0xC4, 0xDF, 0x72, 0xF8, 0xC6, 0x55, 0xE4, 0x7B, 0x14, 0x36, 0x18, 0x3B, 0xA7, 0xD1, 0x20, 0x81, 0x22, 0xD1, 0xA9, 0x18, 0x84, 0x65, 0x13, 0x0B, 0xED, 0xA3, 0x00, 0xE5, 0xD9]; private static RSAParameters LoadParameters = new RSAParameters() @@ -197,6 +208,7 @@ namespace EpinelPS.StaticInfo outputStream.WriteByte((byte)(((byte)b) ^ mask)); } } + public static async Task Load() { var targetFile = await AssetDownloadUtil.DownloadOrGetFileAsync(GameConfig.Root.StaticData.Url, CancellationToken.None); @@ -205,6 +217,7 @@ namespace EpinelPS.StaticInfo _instance = new(targetFile); } #endregion + private async Task LoadZip(string entry, ProgressBar bar) { var mainQuestData = MainZip.GetEntry(entry); @@ -213,7 +226,6 @@ namespace EpinelPS.StaticInfo using StreamReader mainQuestReader = new StreamReader(MainZip.GetInputStream(mainQuestData)); var mainQuestDataString = await mainQuestReader.ReadToEndAsync(); - var questdata = JsonConvert.DeserializeObject(mainQuestDataString); if (questdata == null) throw new Exception("failed to parse " + entry); @@ -222,6 +234,7 @@ namespace EpinelPS.StaticInfo return questdata; } + private async Task LoadZip(string entry, ProgressBar bar) { var mainQuestData = MainZip.GetEntry(entry); @@ -230,7 +243,6 @@ namespace EpinelPS.StaticInfo using StreamReader mainQuestReader = new StreamReader(MainZip.GetInputStream(mainQuestData)); var mainQuestDataString = await mainQuestReader.ReadToEndAsync(); - var questdata = JObject.Parse(mainQuestDataString); if (questdata == null) throw new Exception("failed to parse " + entry); @@ -243,6 +255,7 @@ namespace EpinelPS.StaticInfo return records; } + int totalFiles = 78; int currentFile = 0; @@ -347,18 +360,62 @@ namespace EpinelPS.StaticInfo } } } + var battleOutpostTable = await LoadZip("OutpostBattleTable.json", progress); + foreach (var obj in battleOutpostTable.records) + { + OutpostBattle.Add(obj.id, obj); + } + + var gachaTypeTable = await LoadZip("GachaTypeTable.json", progress); + // Add the records to the dictionary + foreach (var obj in gachaTypeTable.records) + { + gachaTypes.Add(obj.id, obj); // Use obj.id as the key and obj (the GachaType) as the value + } + + var eventManagerTable = await LoadZip("EventManagerTable.json", progress); - var fieldItems = await LoadZip("FieldItemTable.json", progress); - foreach (var obj in fieldItems.records) + // Add the records to the dictionary + foreach (var obj in eventManagerTable.records) + { + eventManagers.Add(obj.id, obj); // Use obj.id as the key and obj (the EventManager) as the value + } + + + // Load Jukebox data + await LoadJukeboxListData(progress); + await LoadJukeboxThemeData(progress); + } + + public async Task LoadJukeboxListData(ProgressBar bar) + { + var jukeboxListData = await LoadZip("JukeboxListTable.json", bar); + foreach (JObject obj in jukeboxListData) { - FieldItems.Add(obj.id, obj); + var record = obj.ToObject(); + if (record != null) + { + jukeboxListDataRecords.Add(record.id, record); + } } + } + + public Dictionary GetJukeboxListDataRecords() + { + return jukeboxListDataRecords; + } - var battleOutpostTable = await LoadZip("OutpostBattleTable.json", progress); - foreach (var obj in battleOutpostTable.records) + public async Task LoadJukeboxThemeData(ProgressBar bar) + { + var jukeboxThemeData = await LoadZip("JukeboxThemeTable.json", bar); + foreach (JObject obj in jukeboxThemeData) { - OutpostBattle.Add(obj.id, obj); + var record = obj.ToObject(); + if (record != null) + { + jukeboxThemeDataRecords.Add(record.id, record); + } } } @@ -507,5 +564,18 @@ namespace EpinelPS.StaticInfo { return TacticAcademyLessons[lessonId]; } + + // Methods to access Jukebox data + public JukeboxListRecord? GetJukeboxListRecordById(int id) + { + jukeboxListDataRecords.TryGetValue(id, out var record); + return record; + } + + public JukeboxThemeRecord? GetJukeboxThemeRecordById(int id) + { + jukeboxThemeDataRecords.TryGetValue(id, out var record); + return record; + } } } diff --git a/EpinelPS/GameData/JsonStaticData.cs b/EpinelPS/GameData/JsonStaticData.cs index cda31e2..b789f1f 100644 --- a/EpinelPS/GameData/JsonStaticData.cs +++ b/EpinelPS/GameData/JsonStaticData.cs @@ -130,7 +130,9 @@ public class CharacterRecord { public int id; - // TODO: There is more stuff here but it isn't needed yet + public int piece_id; + public string original_rare; + public string corporation; } public class CharacterTable { @@ -159,7 +161,39 @@ { public List records; } + public class JukeboxListRecord + { + public int id; + public int theme; + public string bgm ; + public bool is_loop; + public int play_time; + public string name ; + public int order; + public string artist; + public string get_info_type; + public string get_info_value; + } + public class JukeboxListTable + { + public List records; + } + + public class JukeboxThemeRecord + { + public int id; + public string name_localkey; + public string description_localkey; + public int order; + public string theme_resource; + public string bg_color; + } + + public class JukeboxThemeTable + { + public List records; + } public class OutpostBattleTableRecord { public int id; @@ -172,4 +206,68 @@ { public List records; } + + public class GachaPriceGroup + { + public int gacha_price_type; + public int gacha_price_value_count_1; + public int daily_gacha_discount_price_value_1; + public int gacha_price_value_count_10; + } + + public class GachaType + { + public int id; + public string type; + public int order_id; + public int event_id; + public string gacha_provide_count_type; + public bool use_daily_discount_one; + public int daily_free_gacha_event_id; + public List gacha_price_group; + public int grade_prob_id; + public bool is_max_count; + public int max_ceiling_count; + public int fixed_char_amount; + public string gacha_page_prefab; + public int pickup_char_group_id; + public bool use_wish_list; + public int gacha_play_max_count; + public int gacha_reward_id; + public int gacha_play_max_count_reward_id; + public int previous_gacha_id; + } + + public class GachaTypeTable + { + public List records; + } + + public class EventManager + { + public int id; + public string event_system_type; + public string event_shortcut_id; + public string name_localkey; + public string description_localkey; + public string schedule_type; + public string schedule_value; + public string event_disable_locale; + public string event_resource_id; + public string event_thumbnail_resource_table; + public string event_thumbnail_resource_id; + public string thumbnail_color; + public string event_banner_resource_table; + public string event_banner_resource_id; + public long event_order; + public bool is_popup; + public string active_type; + public string banner_print_type; + } + + public class EventManagerTable + { + public List records; + } + } diff --git a/EpinelPS/LobbyServer/Msgs/Event/ListEvents.cs b/EpinelPS/LobbyServer/Msgs/Event/ListEvents.cs index 19d4a15..4f59e15 100644 --- a/EpinelPS/LobbyServer/Msgs/Event/ListEvents.cs +++ b/EpinelPS/LobbyServer/Msgs/Event/ListEvents.cs @@ -100,8 +100,8 @@ namespace EpinelPS.LobbyServer.Msgs.Event response.EventList.Add(new NetEventData() { - Id = 40053, - EventSystemType = 5, + Id = 70034, + EventSystemType = 6, EventVisibleDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks, EventStartDate = DateTime.UtcNow.Subtract(TimeSpan.FromDays(1)).Ticks, EventEndDate = DateTime.Now.AddDays(20).Ticks, diff --git a/EpinelPS/LobbyServer/Msgs/Gacha/ExecGacha.cs b/EpinelPS/LobbyServer/Msgs/Gacha/ExecGacha.cs index 7971f70..c370da2 100644 --- a/EpinelPS/LobbyServer/Msgs/Gacha/ExecGacha.cs +++ b/EpinelPS/LobbyServer/Msgs/Gacha/ExecGacha.cs @@ -2,45 +2,185 @@ using EpinelPS.StaticInfo; using EpinelPS.Utils; + namespace EpinelPS.LobbyServer.Msgs.Gacha { [PacketPath("/gacha/execute")] public class ExecGacha : LobbyMsgHandler { + private static readonly Random random = new Random(); + + // Exclusion lists for sick pulls mode and normal mode 2500601 is the broken R rarity dorothy + private static readonly List sickPullsExclusionList = new List { 2500601 }; // Add more IDs as needed + private static readonly List normalPullsExclusionList = new List { 2500601 }; // Add more IDs as needed + protected override async Task HandleAsync() { var req = await ReadData(); var user = GetUser(); - var response = new ResExecuteGacha(); - // TODO: Pick random character that player does not have unless it supports limit break. + var allCharacterData = GameData.Instance.characterTable.Values.ToList(); - // TODO implement reward - response.Reward = new NetRewardData(); + // Separate characters by rarity categories + var rCharacters = allCharacterData.Where(c => c.original_rare == "R").ToList(); + var srCharacters = allCharacterData.Where(c => c.original_rare == "SR").ToList(); + + // Separate Pilgrim SSRs and non-Pilgrim SSRs + var pilgrimCharacters = allCharacterData.Where(c => c.original_rare == "SSR" && c.corporation == "PILGRIM").ToList(); + var ssrCharacters = allCharacterData.Where(c => c.original_rare == "SSR" && c.corporation != "PILGRIM").ToList(); - foreach (var c in GameData.Instance.GetAllCharacterTids()) + var selectedCharacters = new List(); + + // Check if user has 'sickpulls' set to true to use old method + if (user.sickpulls) { - if (!user.HasCharacter(c)) + // Old selection method: Randomly select 10 characters without rarity-based selection, excluding characters in the sickPullsExclusionList + selectedCharacters = allCharacterData + .Where(c => !sickPullsExclusionList.Contains(c.id)) // Exclude characters based on the exclusion list for sick pulls + .OrderBy(x => random.Next()) + .Take(10) + .ToList(); + } + else + { + // New method: Select 10 characters, with each character having its category determined independently, excluding characters in the normalPullsExclusionList + for (int i = 0; i < 10; i++) { - var id = user.GenerateUniqueCharacterId(); - response.Gacha.Add(new NetGachaEntityData() { Corporation = 1, PieceCount = 1, CurrencyValue = 5, Sn = id, Tid = c, Type = 1 }); - - response.Characters.Add(new NetUserCharacterDefaultData() { CostumeId = 0, Csn = id, Grade = 0, Level = 1, Skill1Lv = 1, Skill2Lv = 1, Tid = c, UltiSkillLv = 1 }); - - user.Characters.Add(new Database.Character() { CostumeId = 0, Csn = id, Grade = 0, Level = 1, Skill1Lvl = 1, Skill2Lvl = 1, Tid = c, UltimateLevel = 1 }); - } - else - { - // TODO add spare body + var character = SelectRandomCharacter(rCharacters, srCharacters, ssrCharacters, pilgrimCharacters, normalPullsExclusionList); + selectedCharacters.Add(character); } } + + var pieceIds = new List>(); // 2D array to store characterId and pieceId as Tuple + + // Populate the 2D array with characterId and pieceId for each selected character + foreach (var characterData in selectedCharacters) + { + var characterId = characterData.id; + var pieceId = characterData.piece_id; + + // Store characterId and pieceId in the array + pieceIds.Add(Tuple.Create(characterId, pieceId)); + + var id = user.GenerateUniqueCharacterId(); + response.Gacha.Add(new NetGachaEntityData() + { + Corporation = 1, + PieceCount = 1, + CurrencyValue = 5, + Sn = id, + Tid = characterId, + Type = 1 + }); + + // Check if the user already has the character, if not add it + if (!user.HasCharacter(characterId)) + { + response.Characters.Add(new NetUserCharacterDefaultData() + { + CostumeId = 0, + Csn = id, + Grade = 0, + Level = 1, + Skill1Lv = 1, + Skill2Lv = 1, + Tid = characterId, + UltiSkillLv = 1 + }); + } + + if (!user.HasCharacter(characterId)) + { + user.Characters.Add(new Database.Character() + { + CostumeId = 0, + Csn = id, + Grade = 0, + Level = 1, + Skill1Lvl = 1, + Skill2Lvl = 1, + Tid = characterId, + UltimateLevel = 1 + }); + } + } + + // Add each character's item to user.Items if the character exists in user.Characters + foreach (var characterData in selectedCharacters) + { + if (user.Characters.Any(c => c.Tid == characterData.id)) + { + user.Items.Add(new Database.ItemData() + { + ItemType = characterData.piece_id, // Assuming item id corresponds to character id + Csn = characterData.piece_id, + Count = 1, // or any relevant count + Level = 0, + Exp = 0, + Position = 0, + Corp = 0, + Isn = user.GenerateUniqueItemId() + }); + response.Items.Add(new NetUserItemData() + { + Tid = characterData.piece_id, // Assuming item id corresponds to character id + Csn = characterData.piece_id, + Count = 1, // or any relevant count + Level = 0, + Exp = 0, + Position = 0, + Isn = user.GenerateUniqueItemId() + }); + } + } + user.GachaTutorialPlayCount++; - JsonDb.Save(); - await WriteDataAsync(response); } + + private CharacterRecord SelectRandomCharacter(List rCharacters, List srCharacters, List ssrCharacters, List pilgrimCharacters, List exclusionList) + { + // Remove excluded characters from each category + var availableRCharacters = rCharacters.Where(c => !exclusionList.Contains(c.id)).ToList(); + var availableSRCharacters = srCharacters.Where(c => !exclusionList.Contains(c.id)).ToList(); + var availableSSRCharacters = ssrCharacters.Where(c => !exclusionList.Contains(c.id)).ToList(); + var availablePilgrimCharacters = pilgrimCharacters.Where(c => !exclusionList.Contains(c.id)).ToList(); + + // Each time we call this method, a new category will be selected for a single character + double roll = random.NextDouble() * 100; // Roll from 0 to 100 + + if (roll < 53 && availableRCharacters.Any()) + { + // R category + return availableRCharacters[random.Next(availableRCharacters.Count)]; + } + else if (roll < 53 + 43 && availableSRCharacters.Any()) + { + // SR category + return availableSRCharacters[random.Next(availableSRCharacters.Count)]; + } + else + { + // SSR category + double ssrRoll = random.NextDouble() * 100; + + if (ssrRoll < 4.55 && availablePilgrimCharacters.Any()) + { + // PILGRIM SSR + return availablePilgrimCharacters[random.Next(availablePilgrimCharacters.Count)]; + } + else if (availableSSRCharacters.Any()) + { + // Non-PILGRIM SSR + return availableSSRCharacters[random.Next(availableSSRCharacters.Count)]; + } + } + + // Fallback to a random R character if somehow no SSR characters are left after exclusion + return availableRCharacters.Any() ? availableRCharacters[random.Next(availableRCharacters.Count)] : null; + } } } diff --git a/EpinelPS/LobbyServer/Msgs/GetGacha.cs b/EpinelPS/LobbyServer/Msgs/GetGacha.cs index 2e22a4c..4e226f9 100644 --- a/EpinelPS/LobbyServer/Msgs/GetGacha.cs +++ b/EpinelPS/LobbyServer/Msgs/GetGacha.cs @@ -1,4 +1,5 @@ using EpinelPS.Utils; +using EpinelPS.StaticInfo; namespace EpinelPS.LobbyServer.Msgs { @@ -11,8 +12,24 @@ namespace EpinelPS.LobbyServer.Msgs var user = GetUser(); var response = new ResGetGachaData(); + + // Adding a default GachaType if the tutorial is done if (user.GachaTutorialPlayCount > 0) + { response.Gacha.Add(new NetUserGachaData() { GachaType = 3, PlayCount = 1 }); + } + + // Now let's loop through gachaTypes and add those with "type" == "GachaPickup" + foreach (var gacha in GameData.Instance.gachaTypes.Values) // We're looping through the dictionary's values + { + if (gacha.type == "GachaPickup") + { + // Add this GachaType ID to the response + response.Gacha.Add(new NetUserGachaData() { GachaType = gacha.id, PlayCount = 1 }); + } + } + + // Write the response back await WriteDataAsync(response); } } diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ChangeMasterRole.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ChangeMasterRole.cs new file mode 100644 index 0000000..25224b6 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ChangeMasterRole.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/changemasterrole")] + public class ChangeDaveMasterRole : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResChangeDaveMasterRole + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ClearBag.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ClearBag.cs new file mode 100644 index 0000000..85e456a --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ClearBag.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/clearbagnew")] + public class ClearDaveBagNewIcon : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResClearDaveBagNewIcon + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ClearSushi.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ClearSushi.cs new file mode 100644 index 0000000..4280b00 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ClearSushi.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/clearsushinew")] + public class ClearDaveSushiNewIcon : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResClearDaveSushiNewIcon + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/CompleteDive.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/CompleteDive.cs new file mode 100644 index 0000000..ae70442 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/CompleteDive.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.Collections; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/completedive")] + public class CompleteDaveDive : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResCompleteDaveDive + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/CompleteSushi.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/CompleteSushi.cs new file mode 100644 index 0000000..7b8460c --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/CompleteSushi.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.Collections; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/completesushi")] + public class CompleteDaveSushi : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResCompleteDaveSushi + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DeductItems.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DeductItems.cs new file mode 100644 index 0000000..d2818e6 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DeductItems.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.Collections; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/deductitem")] + public class DeductDaveItem : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResDeductDaveItem + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DiverAllTriggers.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DiverAllTriggers.cs new file mode 100644 index 0000000..b0a8dbe --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DiverAllTriggers.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.Collections; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/getalldavetrigger")] + public class GetAllMiniGameDaveTriggers : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetAllMiniGameDaveTriggers + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DiverGetData.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DiverGetData.cs new file mode 100644 index 0000000..48770a6 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DiverGetData.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/getdata")] + public class GetDaveData : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetDaveData + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DriftBottle.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DriftBottle.cs new file mode 100644 index 0000000..bbe9325 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/DriftBottle.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.Collections; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/driftbottle")] + public class MiniGameDaveDriftBottle : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResMiniGameDaveDriftBottle + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/GetRanking.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/GetRanking.cs new file mode 100644 index 0000000..61a4835 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/GetRanking.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/getranking")] + public class GetMiniGameDaveRanking : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + + var response = new ResGetMiniGameDaveRanking + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/MissionReward.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/MissionReward.cs new file mode 100644 index 0000000..9a5208a --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/MissionReward.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/obtainmissionreward")] + public class ObtainMiniGameDaveMissionReward : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResObtainMiniGameDaveMissionReward + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ReportRoundFlow.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ReportRoundFlow.cs new file mode 100644 index 0000000..a89356d --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/ReportRoundFlow.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; +using Google.Protobuf.Collections; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/reportdiverroundflow")] + public class ReportDiverRoundFlow : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResReportDiverRoundFlow + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/SetMenus.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/SetMenus.cs new file mode 100644 index 0000000..c9b8b44 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/SetMenus.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/setmenus")] + public class SetDaveSushiMenus : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResSetDaveSushiMenus + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/SushiEmploy.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/SushiEmploy.cs new file mode 100644 index 0000000..a3c885c --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/SushiEmploy.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/sushiemploy")] + public class DaveSushiEmployee : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResDaveSushiEmployee + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UnlockRole.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UnlockRole.cs new file mode 100644 index 0000000..ede4d8e --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UnlockRole.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/unlockrole")] + public class UnlockDaveRole : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResUnlockDaveRole + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UnlockSushi.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UnlockSushi.cs new file mode 100644 index 0000000..2bf90e1 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UnlockSushi.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/unlocksushi")] + public class DaveUnlockSushi : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResDaveUnlockSushi + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UpgradeSushi.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UpgradeSushi.cs new file mode 100644 index 0000000..9299f4d --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UpgradeSushi.cs @@ -0,0 +1,21 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/upgradesushi")] + public class UpgradeDaveSushi : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + + var response = new ResUpgradeDaveSushi + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UpgradeWeapon.cs b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UpgradeWeapon.cs new file mode 100644 index 0000000..b57cec0 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/Dave/UpgradeWeapon.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("event/minigame/dave/upgradeequipment")] + public class UpgradeDaveEquipment : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResUpgradeDaveEquipment + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/EventCurrency.cs b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/EventCurrency.cs new file mode 100644 index 0000000..49f8dd3 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/EventCurrency.cs @@ -0,0 +1,19 @@ +using EpinelPS.Utils; +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("/event/minigame/islandadventure/get/currency")] + public class MiniGameIslandAdventureCurrency : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetMiniGameIslandAdventureCurrency + { + Currency = 90000 + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/EventInventory.cs b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/EventInventory.cs new file mode 100644 index 0000000..6a76bc4 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/EventInventory.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("/event/minigame/islandadventure/get/inventory")] + public class MiniGameIslandAdventureInventory : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResGetMiniGameIslandAdventureInventory + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/FishSpotCount.cs b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/FishSpotCount.cs new file mode 100644 index 0000000..19cec5f --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/FishSpotCount.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("/event/minigame/islandadventure/get/fish/spotcount")] + public class MiniGameIslandAdventureFishingSpotCountHistory : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResMiniGameIslandAdventureFishingSpotCountHistory + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/PhotoData.cs b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/PhotoData.cs new file mode 100644 index 0000000..96e7bc6 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Minigame/IslandAdventure/PhotoData.cs @@ -0,0 +1,20 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Event +{ + [PacketPath("/event/minigame/islandadventure/get/photo/album")] + public class MiniGameIslandAdventurePhotoAlbum : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResMiniGameIslandAdventurePhotoAlbum + { + + }; + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs b/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs index 1386844..47472cf 100644 --- a/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs +++ b/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs @@ -1,5 +1,6 @@ using EpinelPS.Utils; - +using EpinelPS.Database; +using EpinelPS.StaticInfo; namespace EpinelPS.LobbyServer.Msgs.Outpost { [PacketPath("/outpost/getoutpostdata")] @@ -20,16 +21,24 @@ namespace EpinelPS.LobbyServer.Msgs.Outpost { OutpostBattleLevel = user.OutpostBattleLevel, Jukebox = new() { SelectTid = 5 }, - JukeboxV2 = new NetUserJukeboxDataV2() { CommandBgm = new() { Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, JukeboxTableId = 5 } }, + JukeboxV2 = new NetUserJukeboxDataV2() { CommandBgm = new() { Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, JukeboxTableId = JsonDb.CurrentJukeboxBgm(2) } }, BattleTime = 864000000000, MaxBattleTime = 864000000000, SkinGroupId = 1000, }; // TODO: do not hard code this! - response.Jukebox.List.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); - response.JukeboxV2.JukeboxTableIds.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + //response.Jukebox.List.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + //response.JukeboxV2.JukeboxTableIds.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + + // Directly use jukeboxListDataRecords + var jukeboxIds = GameData.Instance.jukeboxListDataRecords.Keys.ToList(); + + // Update response lists with the IDs + response.Jukebox.List.AddRange(jukeboxIds); + response.JukeboxV2.JukeboxTableIds.AddRange(jukeboxIds); + response.OutpostBattleLevel = user.OutpostBattleLevel; response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs, OverBattleTime = overBattleTime }; diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs.bak b/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs.bak new file mode 100644 index 0000000..1386844 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Outpost/GetOutpostData.cs.bak @@ -0,0 +1,54 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Outpost +{ + [PacketPath("/outpost/getoutpostdata")] + public class GetOutpostData : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var battleTime = DateTime.UtcNow - user.BattleTime; + var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100); + + long overBattleTime = battleTimeMs > 12096000000000 ? battleTimeMs - 12096000000000 : 0; + + + var response = new ResGetOutpostData + { + OutpostBattleLevel = user.OutpostBattleLevel, + Jukebox = new() { SelectTid = 5 }, + JukeboxV2 = new NetUserJukeboxDataV2() { CommandBgm = new() { Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, JukeboxTableId = 5 } }, + BattleTime = 864000000000, + MaxBattleTime = 864000000000, + SkinGroupId = 1000, + }; + + // TODO: do not hard code this! + response.Jukebox.List.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + response.JukeboxV2.JukeboxTableIds.AddRange([5, 9999901, 4001, 4002, 4003, 4004, 4005, 4006, 12, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019, 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012]); + + response.OutpostBattleLevel = user.OutpostBattleLevel; + response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs, OverBattleTime = overBattleTime }; + + response.Data.Add(new NetUserOutpostData() { SlotId = 1, BuildingId = 22401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 4, BuildingId = 22701, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 5, BuildingId = 22801, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 6, BuildingId = 22901, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 7, BuildingId = 23001, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 3, BuildingId = 23101, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 2, BuildingId = 23201, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 9, BuildingId = 23301, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 8, BuildingId = 23401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 10, BuildingId = 23501, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Data.Add(new NetUserOutpostData() { SlotId = 38, BuildingId = 33601, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + + response.TimeRewardBuffs.AddRange(NetUtils.GetOutpostTimeReward(user)); + + // TODO + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/JukeboxGet.cs b/EpinelPS/LobbyServer/Msgs/Outpost/JukeboxGet.cs new file mode 100644 index 0000000..ac69346 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Outpost/JukeboxGet.cs @@ -0,0 +1,30 @@ +using EpinelPS.Utils; + + +namespace EpinelPS.LobbyServer.Msgs.Jukebox +{ + [PacketPath("/jukebox/playlist/get")] + public class JukeboxPlaylistGet : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + // Prepare response with static data + var response = new ResGetJukeboxPlaylist + { + Playlists = {}, // Assuming Playlists is a list or similar collection type, you may want to add items here. + FavoriteSongs = new NetJukeboxFavorite + { + Songs = + { + new NetJukeboxPlaylistSong { JukeboxTableId = 8995001,Order = 899 }, + new NetJukeboxPlaylistSong { JukeboxTableId = 9020001, Order = 902 } + } + }, + // JukeboxPlaylistUid = 123456789 // Assign a static UID, if required + }; + + // Send the response + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/Outpost/JukeboxPlayHistory.cs b/EpinelPS/LobbyServer/Msgs/Outpost/JukeboxPlayHistory.cs new file mode 100644 index 0000000..4b53a93 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/Outpost/JukeboxPlayHistory.cs @@ -0,0 +1,16 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.Jukebox +{ + [PacketPath("/jukebox/record/playhistory")] + public class JukeboxPlayHistory : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = ReadData(); + + var response = new ResRecordJukeboxPlayHistory(); + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs b/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs index bdb6334..1660a07 100644 --- a/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs +++ b/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs @@ -23,8 +23,9 @@ namespace EpinelPS.LobbyServer.Msgs.User response.SynchroLv = 1; response.OutpostBattleLevel = user.OutpostBattleLevel; response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs }; - response.CommanderRoomJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = 5, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom }; - response.LobbyJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = 2, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationLobby }; + + response.CommanderRoomJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = JsonDb.CurrentJukeboxBgm(2), Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom }; + response.LobbyJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = JsonDb.CurrentJukeboxBgm(1), Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationLobby }; // Add default slot data if (user.RepresentationTeamData.Slots.Count == 0) diff --git a/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs.bak.bak b/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs.bak.bak new file mode 100644 index 0000000..1660a07 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs.bak.bak @@ -0,0 +1,92 @@ +using EpinelPS.Database; +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.User +{ + [PacketPath("/enterlobbyserver")] + public class EnterLobbyServer : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var battleTime = DateTime.UtcNow - user.BattleTime; + var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100); + + // NOTE: Keep this in sync with GetUser code + + var response = new ResEnterLobbyServer(); + response.User = LobbyHandler.CreateNetUserDataFromUser(user); + response.ResetHour = 20; + response.Nickname = user.Nickname; + response.SynchroLv = 1; + response.OutpostBattleLevel = user.OutpostBattleLevel; + response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs }; + + response.CommanderRoomJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = JsonDb.CurrentJukeboxBgm(2), Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom }; + response.LobbyJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = JsonDb.CurrentJukeboxBgm(1), Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationLobby }; + + // Add default slot data + if (user.RepresentationTeamData.Slots.Count == 0) + { + user.RepresentationTeamData = new NetWholeUserTeamData() { TeamNumber = 1, Type = 2 }; + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 1 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 2 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 3 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 4 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 5 }); + JsonDb.Save(); + } + response.RepresentationTeam = user.RepresentationTeamData; + + foreach (var item in user.Currency) + { + response.Currency.Add(new NetUserCurrencyData() { Type = (int)item.Key, Value = item.Value }); + } + + foreach (var item in user.Characters) + { + response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel}, IsSynchro = user.GetSynchro(item.Csn) }); + } + + foreach (var item in NetUtils.GetUserItems(user)) + { + response.Items.Add(item); + } + + // Add squad data if there are characters + if (user.Characters.Count > 0) + { + var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList(); + response.SynchroLv = user.GetSynchroLevel(); + + foreach (var item in highestLevelCharacters) + { + response.SynchroStandardCharacters.Add(item.Csn); + } + + foreach (var teamInfo in user.UserTeams) + response.TypeTeams.Add(teamInfo.Value); + } + + // TODO: Save outpost data + response.Outposts.Add(new NetUserOutpostData() { SlotId = 1, BuildingId = 22401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 4, BuildingId = 22701, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 5, BuildingId = 22801, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 6, BuildingId = 22901, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 7, BuildingId = 23001, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 3, BuildingId = 23101, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 2, BuildingId = 23201, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 9, BuildingId = 23301, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 8, BuildingId = 23401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 10, BuildingId = 23501, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 38, BuildingId = 33601, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + + response.LastClearedNormalMainStageId = user.LastNormalStageCleared; + response.TimeRewardBuffs.AddRange(NetUtils.GetOutpostTimeReward(user)); + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs.bak.bak.bak b/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs.bak.bak.bak new file mode 100644 index 0000000..bdb6334 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/User/EnterLobbyServer.cs.bak.bak.bak @@ -0,0 +1,91 @@ +using EpinelPS.Database; +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.User +{ + [PacketPath("/enterlobbyserver")] + public class EnterLobbyServer : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + var user = GetUser(); + + var battleTime = DateTime.UtcNow - user.BattleTime; + var battleTimeMs = (long)(battleTime.TotalNanoseconds / 100); + + // NOTE: Keep this in sync with GetUser code + + var response = new ResEnterLobbyServer(); + response.User = LobbyHandler.CreateNetUserDataFromUser(user); + response.ResetHour = 20; + response.Nickname = user.Nickname; + response.SynchroLv = 1; + response.OutpostBattleLevel = user.OutpostBattleLevel; + response.OutpostBattleTime = new NetOutpostBattleTime() { MaxBattleTime = 864000000000, MaxOverBattleTime = 12096000000000, BattleTime = battleTimeMs }; + response.CommanderRoomJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = 5, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom }; + response.LobbyJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = 2, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationLobby }; + + // Add default slot data + if (user.RepresentationTeamData.Slots.Count == 0) + { + user.RepresentationTeamData = new NetWholeUserTeamData() { TeamNumber = 1, Type = 2 }; + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 1 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 2 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 3 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 4 }); + user.RepresentationTeamData.Slots.Add(new NetWholeTeamSlot() { Slot = 5 }); + JsonDb.Save(); + } + response.RepresentationTeam = user.RepresentationTeamData; + + foreach (var item in user.Currency) + { + response.Currency.Add(new NetUserCurrencyData() { Type = (int)item.Key, Value = item.Value }); + } + + foreach (var item in user.Characters) + { + response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel}, IsSynchro = user.GetSynchro(item.Csn) }); + } + + foreach (var item in NetUtils.GetUserItems(user)) + { + response.Items.Add(item); + } + + // Add squad data if there are characters + if (user.Characters.Count > 0) + { + var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList(); + response.SynchroLv = user.GetSynchroLevel(); + + foreach (var item in highestLevelCharacters) + { + response.SynchroStandardCharacters.Add(item.Csn); + } + + foreach (var teamInfo in user.UserTeams) + response.TypeTeams.Add(teamInfo.Value); + } + + // TODO: Save outpost data + response.Outposts.Add(new NetUserOutpostData() { SlotId = 1, BuildingId = 22401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 4, BuildingId = 22701, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 5, BuildingId = 22801, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 6, BuildingId = 22901, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 7, BuildingId = 23001, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 3, BuildingId = 23101, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 2, BuildingId = 23201, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 9, BuildingId = 23301, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 8, BuildingId = 23401, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 10, BuildingId = 23501, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + response.Outposts.Add(new NetUserOutpostData() { SlotId = 38, BuildingId = 33601, IsDone = true, StartAt = 638549982076760660, CompleteAt = 638549982076760660 }); + + response.LastClearedNormalMainStageId = user.LastNormalStageCleared; + response.TimeRewardBuffs.AddRange(NetUtils.GetOutpostTimeReward(user)); + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/LobbyServer/Msgs/User/GetUser.cs b/EpinelPS/LobbyServer/Msgs/User/GetUser.cs index a24d9c6..16f2a4f 100644 --- a/EpinelPS/LobbyServer/Msgs/User/GetUser.cs +++ b/EpinelPS/LobbyServer/Msgs/User/GetUser.cs @@ -1,4 +1,5 @@ using EpinelPS.Utils; +using EpinelPS.Database; namespace EpinelPS.LobbyServer.Msgs.User { @@ -38,8 +39,8 @@ namespace EpinelPS.LobbyServer.Msgs.User response.User.Tutorials.Add(new NetTutorialData() { GroupId = groupId, LastClearedTid = item.Key, LastClearedVersion = version }); } - response.CommanderRoomJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = 2, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom }; - response.LobbyJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = 2, Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationLobby }; + response.CommanderRoomJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = JsonDb.CurrentJukeboxBgm(2), Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationCommanderRoom }; + response.LobbyJukeboxBgm = new NetJukeboxBgm() { JukeboxTableId = JsonDb.CurrentJukeboxBgm(1), Type = NetJukeboxBgmType.NetJukeboxBgmTypeJukeboxTableId, Location = NetJukeboxLocation.NetJukeboxLocationLobby }; await WriteDataAsync(response); } diff --git a/EpinelPS/LobbyServer/Msgs/User/SetUserTitle.cs b/EpinelPS/LobbyServer/Msgs/User/SetUserTitle.cs new file mode 100644 index 0000000..1669996 --- /dev/null +++ b/EpinelPS/LobbyServer/Msgs/User/SetUserTitle.cs @@ -0,0 +1,17 @@ +using EpinelPS.Utils; + +namespace EpinelPS.LobbyServer.Msgs.User +{ + [PacketPath("/lobby/usertitle/set")] + public class SetUserTitleData : LobbyMsgHandler + { + protected override async Task HandleAsync() + { + var req = await ReadData(); + + var response = new ResSetUserTitle(); + + await WriteDataAsync(response); + } + } +} diff --git a/EpinelPS/Program.cs b/EpinelPS/Program.cs index 3f56912..43371d0 100644 --- a/EpinelPS/Program.cs +++ b/EpinelPS/Program.cs @@ -208,7 +208,12 @@ namespace EpinelPS Console.WriteLine(" unban - unban selected user from game"); Console.WriteLine(" exit - exit server application"); Console.WriteLine(" completestage (chapter num)-(stage number) - complete selected stage and get rewards (and all previous ones). Example completestage 15-1. Note that the exact stage number cleared may not be exact."); - } + Console.WriteLine(" sickpulls (requires selecting user first) allows for all characters to have equal chances of getting pulled"); + Console.WriteLine(" SetLevel (level) - Set all characters' level (between 1 and 999 takes effect on game and server restart)"); + Console.WriteLine(" SetSkillLevel (level) - Set all characters' skill levels between 1 and 10 (takes effect on game and server restart)"); + Console.WriteLine(" addallcharacters - Add all missing characters to the selected user with default levels and skills (takes effect on game and server restart)"); + + } else if (input == "ls /users") { Console.WriteLine("Id,Username,Nickname"); @@ -248,6 +253,146 @@ namespace EpinelPS Console.WriteLine("Usage: chroot (user id)"); } } + else if (input == "addallcharacters") + { + if (selectedUser == 0) + { + Console.WriteLine("No user selected"); + } + else + { + var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser); + if (user == null) + { + Console.WriteLine("Selected user does not exist"); + selectedUser = 0; + prompt = "# "; + } + else + { + // Add all characters to the selected user + foreach (var c in GameData.Instance.GetAllCharacterTids()) + { + if (!user.HasCharacter(c)) + { + // Generate a unique character ID + int id = user.GenerateUniqueCharacterId(); + user.Characters.Add(new Database.Character() + { + CostumeId = 0, + Csn = id, + Grade = 0, + Level = 1, + Skill1Lvl = 1, + Skill2Lvl = 1, + Tid = c, + UltimateLevel = 1 + }); + } + } + Console.WriteLine("Added all missing characters to user " + user.Username); + JsonDb.Save(); + } + } + } + else if (input == "sickpulls") + { + if (selectedUser == 0) + { + Console.WriteLine("No user selected"); + } + else + { + var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser); + if (user == null) + { + Console.WriteLine("Selected user does not exist"); + selectedUser = 0; + prompt = "# "; + } + else + { + // Check current value of sickpulls and toggle it + bool currentSickPulls = EpinelPS.Database.JsonDb.IsSickPulls(user); + if (currentSickPulls) + { + user.sickpulls = false; + Console.WriteLine("sickpulls is now set to false for user " + user.Username); + } + else + { + user.sickpulls = true; + Console.WriteLine("sickpulls is now set to true for user " + user.Username); + } + + // Save the changes to the database + JsonDb.Save(); + } + } + } + else if (input.StartsWith("SetLevel")) + { + if (selectedUser == 0) + { + Console.WriteLine("No user selected"); + } + else + { + var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser); + if (user == null) + { + Console.WriteLine("Selected user does not exist"); + selectedUser = 0; + prompt = "# "; + } + else if (args.Length == 2 && int.TryParse(args[1], out int level) && level >= 1 && level <= 999) + { + foreach (var character in user.Characters) + { + character.Level = level; + } + Console.WriteLine("Set all characters' level to " + level); + JsonDb.Save(); + } + else + { + Console.WriteLine("Invalid argument. Level must be between 1 and 999."); + } + } + } + else if (input.StartsWith("SetSkillLevel")) + { + if (selectedUser == 0) + { + Console.WriteLine("No user selected"); + } + else + { + var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser); + if (user == null) + { + Console.WriteLine("Selected user does not exist"); + selectedUser = 0; + prompt = "# "; + } + else if (args.Length == 2 && int.TryParse(args[1], out int skillLevel) && skillLevel >= 1 && skillLevel <= 10) + { + foreach (var character in user.Characters) + { + character.UltimateLevel = skillLevel; + character.Skill1Lvl = skillLevel; + character.Skill2Lvl = skillLevel; + } + Console.WriteLine("Set all characters' skill levels to " + skillLevel); + JsonDb.Save(); + } + else + { + Console.WriteLine("Invalid argument. Skill level must be between 1 and 10."); + } + } + } + else if (input.StartsWith("rmuser")) { if (selectedUser == 0)