From dd8062dd4db2a00fe23b4b52a04c7bfe3d798ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=82ngelo=20Tadeucci?= Date: Thu, 19 Jun 2025 20:49:13 -0300 Subject: [PATCH 1/3] bug fixes --- Maple2.Server.Game/Commands/PlayerCommand.cs | 30 +++++++++++++++++++ .../Manager/ItemEnchantManager.cs | 17 +++++------ .../Manager/Items/InventoryManager.cs | 29 +++++++++++++----- .../Manager/Items/StorageManager.cs | 4 ++- Maple2.Server.Game/Manager/QuestManager.cs | 6 ++-- 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/Maple2.Server.Game/Commands/PlayerCommand.cs b/Maple2.Server.Game/Commands/PlayerCommand.cs index bbb7cb041..0228e6217 100644 --- a/Maple2.Server.Game/Commands/PlayerCommand.cs +++ b/Maple2.Server.Game/Commands/PlayerCommand.cs @@ -357,6 +357,7 @@ public InventoryCommand(GameSession session) : base("inventory", "Manage player AddCommand(new ClearInventoryCommand(session)); AddCommand(new SlotsInventoryCommand(session)); AddCommand(new ExpandInventoryCommand(this.session)); + AddCommand(new PrintInventoryCommand(session)); } private class ClearInventoryCommand : Command { @@ -457,6 +458,35 @@ private void Handle(InvocationContext ctx, string tab) { } } } + + private class PrintInventoryCommand : Command { + private readonly GameSession session; + + public PrintInventoryCommand(GameSession session) : base("print", "Print player inventory items.") { + this.session = session; + + var tab = new Argument("tab", $"Inventory tab to print. One of: {string.Join(", ", Enum.GetNames(typeof(InventoryType)))}"); + + AddArgument(tab); + this.SetHandler(Handle, tab); + } + + private void Handle(InvocationContext ctx, string tab) { + try { + if (!Enum.TryParse(tab, true, out InventoryType inventoryType)) { + ctx.Console.Error.WriteLine($"Invalid inventory tab: {tab}. Must be one of: {string.Join(", ", Enum.GetNames(typeof(InventoryType)))}"); + ctx.ExitCode = 1; + return; + } + + ctx.Console.Out.WriteLine(session.Item.Inventory.Print(inventoryType)); + ctx.ExitCode = 0; + } catch (SystemException ex) { + ctx.Console.Error.WriteLine(ex.Message); + ctx.ExitCode = 1; + } + } + } } private class TrophyCommand : Command { diff --git a/Maple2.Server.Game/Manager/ItemEnchantManager.cs b/Maple2.Server.Game/Manager/ItemEnchantManager.cs index dd72131c8..6aec7e09a 100644 --- a/Maple2.Server.Game/Manager/ItemEnchantManager.cs +++ b/Maple2.Server.Game/Manager/ItemEnchantManager.cs @@ -14,13 +14,11 @@ public class ItemEnchantManager { private const int MAX_EXP = 10000; private const int CHARGE_RATE = 1; - // ReSharper disable RedundantExplicitArraySize - private static readonly int[] RequireFodder = new int[15] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 4 }; - private static readonly int[] GainExp = new int[15] { 10000, 10000, 10000, 5000, 5000, 5000, 2500, 2500, 2500, 2000, 3334, 2000, 2000, 1250, 1250 }; - private static readonly int[] SuccessRate = new int[15] { 100, 100, 100, 95, 90, 80, 70, 60, 50, 40, 30, 20, 15, 10, 5 }; - private static readonly int[] FodderRate = new int[15] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 5, 4, 2 }; - private static readonly int[] FailCharge = new int[15] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 5 }; - // ReSharper restore RedundantExplicitArraySize + private static readonly int[] RequireFodder = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, 3, 4]; + private static readonly int[] GainExp = [10000, 10000, 10000, 5000, 5000, 5000, 2500, 2500, 2500, 2000, 3334, 2000, 2000, 1250, 1250]; + private static readonly int[] SuccessRate = [100, 100, 100, 95, 90, 80, 70, 60, 50, 40, 30, 20, 15, 10, 5]; + private static readonly int[] FodderRate = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 7, 5, 4, 2]; + private static readonly int[] FailCharge = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 4, 5]; private static readonly IngredientInfo[][] PeachyCost = new IngredientInfo[15][]; @@ -73,7 +71,7 @@ IngredientInfo[] Build(int onyx, int chaosOnyx, int crystalFragment) { public ItemEnchantManager(GameSession session) { this.session = session; - catalysts = new List(); + catalysts = []; fodders = new Dictionary(); attributeDeltas = new Dictionary(); rates = new EnchantRates(); @@ -147,7 +145,8 @@ public bool UpdateFodder(long itemUid, bool add) { if (add) { // Prevent adding more fodder if it won't help. - if (Type is EnchantType.Ophelia && rates.Total >= MAX_RATE) { + // Can't go over 30% rate with fodders + if (Type is EnchantType.Ophelia && rates.Total >= MAX_RATE || rates.Success + rates.Fodder >= 30) { NpcTalkEvent(ScriptEventType.EnchantFail, ItemEnchantError.max_fodder); return false; } diff --git a/Maple2.Server.Game/Manager/Items/InventoryManager.cs b/Maple2.Server.Game/Manager/Items/InventoryManager.cs index 1d532a35b..ccd3b2505 100644 --- a/Maple2.Server.Game/Manager/Items/InventoryManager.cs +++ b/Maple2.Server.Game/Manager/Items/InventoryManager.cs @@ -1,5 +1,6 @@ using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; +using System.Text; using Maple2.Database.Storage; using Maple2.Model; using Maple2.Model.Enum; @@ -34,13 +35,11 @@ public InventoryManager(GameStorage.Request db, GameSession session) { delete = []; foreach ((InventoryType type, List load) in db.GetInventory(session.CharacterId)) { - if (tabs.TryGetValue(type, out ItemCollection? items)) { - foreach (Item item in load) { - if (items.Add(item).Count == 0) { - Log.Error("Failed to add item:{Uid} to ItemCollection (Size:{Size}, OpenSlots:{OpenSlots}, Count:{Count})", - item.Uid, items.Size, items.OpenSlots, items.Count); - } - } + if (!tabs.TryGetValue(type, out ItemCollection? items)) continue; + foreach (Item item in load) { + if (items.Add(item).Count != 0) continue; + Discard(item); + Log.Warning("Deleted item {ItemUid} from inventory {InventoryType} due to overflow", item.Uid, type); } } } @@ -736,4 +735,20 @@ public void Save(GameStorage.Request db) { } } } + + public string Print(InventoryType type) { + lock (session.Item) { + if (!tabs.TryGetValue(type, out ItemCollection? items)) { + return $"Inventory {type} not found."; + } + + var sb = new StringBuilder(); + sb.AppendLine($"Inventory {type}:"); + foreach (Item item in items) { + sb.AppendLine($"- {item.Id} [{item.Metadata.Name}] (Amount: {item.Amount}, Slot: {item.Slot}, Expiry: {item.ExpiryTime}, Rarity: {item.Rarity}, Tag: {item.Metadata.Property.Tag})"); + } + sb.AppendLine($"Total Items: {items.Count}, Open Slots: {items.OpenSlots}, Size: {items.Size}"); + return sb.ToString(); + } + } } diff --git a/Maple2.Server.Game/Manager/Items/StorageManager.cs b/Maple2.Server.Game/Manager/Items/StorageManager.cs index 51bef85ef..6ee15adf5 100644 --- a/Maple2.Server.Game/Manager/Items/StorageManager.cs +++ b/Maple2.Server.Game/Manager/Items/StorageManager.cs @@ -21,10 +21,12 @@ public sealed class StorageManager : IDisposable { public StorageManager(GameSession session) { this.session = session; - items = new ItemCollection(Constant.BaseStorageCount); using GameStorage.Request db = session.GameStorage.Context(); (mesos, expand) = db.GetStorageInfo(session.AccountId); + + items = new ItemCollection((short) (Constant.BaseStorageCount + expand)); + foreach (Item item in db.GetStorage(session.AccountId)) { if (items.Add(item).Count == 0) { Log.Error("Failed to add storage item:{Uid}", item.Uid); diff --git a/Maple2.Server.Game/Manager/QuestManager.cs b/Maple2.Server.Game/Manager/QuestManager.cs index b3435f4c9..192ba5b0b 100644 --- a/Maple2.Server.Game/Manager/QuestManager.cs +++ b/Maple2.Server.Game/Manager/QuestManager.cs @@ -218,8 +218,7 @@ public void Update(ConditionType type, long counter = 1, string targetString = " condition.Counter = (int) Math.Min(condition.Metadata.Value, condition.Counter + counter); session.Send(QuestPacket.Update(quest)); - if (quest.Metadata.Basic.Type == QuestType.FieldMission && - CanComplete(quest)) { + if (quest.Metadata.Basic.Type == QuestType.FieldMission && CanComplete(quest)) { Complete(quest); } } @@ -370,6 +369,9 @@ public bool Complete(Quest quest, bool bypassConditions = false) { session.ConditionUpdate(ConditionType.quest_clear_by_chapter, codeLong: quest.Metadata.Basic.ChapterId); session.ConditionUpdate(ConditionType.quest, codeLong: quest.Metadata.Id); session.ConditionUpdate(ConditionType.quest_clear, codeLong: quest.Metadata.Id); + if (quest.Metadata.Basic.Type == QuestType.FieldMission) { + session.ConditionUpdate(ConditionType.field_mission); + } quest.EndTime = DateTime.Now.ToEpochSeconds(); quest.State = QuestState.Completed; From cf22a0b0b53542086b3cedfd9cadde896f256b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=82ngelo=20Tadeucci?= Date: Fri, 20 Jun 2025 02:06:42 -0300 Subject: [PATCH 2/3] fix --- Maple2.Server.Game/Manager/ItemEnchantManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maple2.Server.Game/Manager/ItemEnchantManager.cs b/Maple2.Server.Game/Manager/ItemEnchantManager.cs index 6aec7e09a..b7e8e16ae 100644 --- a/Maple2.Server.Game/Manager/ItemEnchantManager.cs +++ b/Maple2.Server.Game/Manager/ItemEnchantManager.cs @@ -146,7 +146,7 @@ public bool UpdateFodder(long itemUid, bool add) { if (add) { // Prevent adding more fodder if it won't help. // Can't go over 30% rate with fodders - if (Type is EnchantType.Ophelia && rates.Total >= MAX_RATE || rates.Success + rates.Fodder >= 30) { + if (Type is EnchantType.Ophelia && rates.Total >= MAX_RATE || rates.Fodder + FodderRate[enchants] > 30) { NpcTalkEvent(ScriptEventType.EnchantFail, ItemEnchantError.max_fodder); return false; } From ad1703552d1a8308a1ae453e0d9e0097e8bdf167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=82ngelo=20Tadeucci?= Date: Fri, 20 Jun 2025 02:11:36 -0300 Subject: [PATCH 3/3] move print inventory command to debug --- Maple2.Server.Game/Commands/DebugCommand.cs | 30 ++++++++++++++++++++ Maple2.Server.Game/Commands/PlayerCommand.cs | 30 -------------------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Maple2.Server.Game/Commands/DebugCommand.cs b/Maple2.Server.Game/Commands/DebugCommand.cs index f7b697e95..d0629240d 100644 --- a/Maple2.Server.Game/Commands/DebugCommand.cs +++ b/Maple2.Server.Game/Commands/DebugCommand.cs @@ -33,6 +33,7 @@ public DebugCommand(GameSession session, NpcMetadataStorage npcStorage, MapDataS AddCommand(new DebugQueryCommand(session, mapDataStorage)); AddCommand(new LogoutCommand(session)); AddCommand(new ReloadCommandsCommand(session)); + AddCommand(new PrintInventoryCommand(session)); } private class ReloadCommandsCommand : Command { @@ -398,4 +399,33 @@ private void Handle(InvocationContext ctx) { session.Disconnect(); } } + + private class PrintInventoryCommand : Command { + private readonly GameSession session; + + public PrintInventoryCommand(GameSession session) : base("print-inventory", "Print player inventory items.") { + this.session = session; + + var tab = new Argument("tab", $"Inventory tab to print. One of: {string.Join(", ", Enum.GetNames(typeof(InventoryType)))}"); + + AddArgument(tab); + this.SetHandler(Handle, tab); + } + + private void Handle(InvocationContext ctx, string tab) { + try { + if (!Enum.TryParse(tab, true, out InventoryType inventoryType)) { + ctx.Console.Error.WriteLine($"Invalid inventory tab: {tab}. Must be one of: {string.Join(", ", Enum.GetNames(typeof(InventoryType)))}"); + ctx.ExitCode = 1; + return; + } + + ctx.Console.Out.WriteLine(session.Item.Inventory.Print(inventoryType)); + ctx.ExitCode = 0; + } catch (SystemException ex) { + ctx.Console.Error.WriteLine(ex.Message); + ctx.ExitCode = 1; + } + } + } } diff --git a/Maple2.Server.Game/Commands/PlayerCommand.cs b/Maple2.Server.Game/Commands/PlayerCommand.cs index 0228e6217..bbb7cb041 100644 --- a/Maple2.Server.Game/Commands/PlayerCommand.cs +++ b/Maple2.Server.Game/Commands/PlayerCommand.cs @@ -357,7 +357,6 @@ public InventoryCommand(GameSession session) : base("inventory", "Manage player AddCommand(new ClearInventoryCommand(session)); AddCommand(new SlotsInventoryCommand(session)); AddCommand(new ExpandInventoryCommand(this.session)); - AddCommand(new PrintInventoryCommand(session)); } private class ClearInventoryCommand : Command { @@ -458,35 +457,6 @@ private void Handle(InvocationContext ctx, string tab) { } } } - - private class PrintInventoryCommand : Command { - private readonly GameSession session; - - public PrintInventoryCommand(GameSession session) : base("print", "Print player inventory items.") { - this.session = session; - - var tab = new Argument("tab", $"Inventory tab to print. One of: {string.Join(", ", Enum.GetNames(typeof(InventoryType)))}"); - - AddArgument(tab); - this.SetHandler(Handle, tab); - } - - private void Handle(InvocationContext ctx, string tab) { - try { - if (!Enum.TryParse(tab, true, out InventoryType inventoryType)) { - ctx.Console.Error.WriteLine($"Invalid inventory tab: {tab}. Must be one of: {string.Join(", ", Enum.GetNames(typeof(InventoryType)))}"); - ctx.ExitCode = 1; - return; - } - - ctx.Console.Out.WriteLine(session.Item.Inventory.Print(inventoryType)); - ctx.ExitCode = 0; - } catch (SystemException ex) { - ctx.Console.Error.WriteLine(ex.Message); - ctx.ExitCode = 1; - } - } - } } private class TrophyCommand : Command {