From 55ac2c3d989956b67b6ab25d2b32cf3933cee2d4 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Thu, 13 Aug 2026 18:43:53 -0700 Subject: [PATCH] refactor: Move legacy deserialization into the .Migrations.cs partials (#2575) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to #2574, which added a `.Migrations.cs` partial to `BaseWeapon`. Pure relocation — no behaviour change. ## The inconsistency `BaseArmor` and `BaseClothing` already kept their pre-codegen `Deserialize(reader, version)` in a `.Migrations.cs` partial, but left the `OldSaveFlag` enum and the `GetSaveFlag` helper behind in the main class file — even though every call site is in the partial: | Class | `Deserialize` | `GetSaveFlag` / `OldSaveFlag` | Call sites outside the partial | |---|---|---|---| | `BaseArmor` | already in partial | in main file | 0 of 26 | | `BaseClothing` | already in partial | in main file | 0 of 12 | | `BaseWeapon` | in main file | in main file | — | `BaseWeapon` had all three still inline, with its new `.Migrations.cs` holding only a `MigrateFrom`. ## After All three follow the same layout: `MigrateFrom` newest to oldest, then the pre-codegen `Deserialize`, then `GetSaveFlag`, then `OldSaveFlag`. That moves ~290 lines of legacy read path out of `BaseWeapon.cs` — the file that needed it most at ~3,900 lines — and leaves the main class files describing only how the type behaves today. ## Reviewing this The diff is large and almost entirely noise, so it is probably not worth reading line by line. Two checks are stronger: - **Nothing was lost or altered.** Across each `.cs` / `.Migrations.cs` pair, the multiset of non-blank source lines is identical to `main` except for one added comment (below). The relocation was done mechanically and asserted against that invariant rather than by hand. - **Nothing about serialization moved with the code.** Running `ModernUOSchemaGenerator` after the move emits no new migration files. The complete set of intentional additions: - `using System;` in each of the three partials, for the `[Flags]` attribute (implicit usings are not enabled here). - `// Version 9 (pre-codegen)` above `BaseWeapon`'s moved `Deserialize`, matching the marker `BaseArmor` and `BaseClothing` already carry. Version 9 is correct because `BaseWeapon.v10.json` is its earliest migration schema, so codegen began at 10. Everything else is blank-line placement. ## Verification Full solution builds in Release with 0 errors and 0 warnings; 1516 tests pass (815 `Server.Tests`, 701 `UOContent.Tests`). --- .../Items/Armor/BaseArmor.Migrations.cs | 34 +++ Projects/UOContent/Items/Armor/BaseArmor.cs | 32 --- .../Items/Clothing/BaseClothing.Migrations.cs | 21 ++ .../UOContent/Items/Clothing/BaseClothing.cs | 18 -- .../Items/Weapons/BaseWeapon.Migrations.cs | 269 ++++++++++++++++++ .../UOContent/Items/Weapons/BaseWeapon.cs | 266 ----------------- 6 files changed, 324 insertions(+), 316 deletions(-) diff --git a/Projects/UOContent/Items/Armor/BaseArmor.Migrations.cs b/Projects/UOContent/Items/Armor/BaseArmor.Migrations.cs index f01bfad16..f15a7fd6a 100644 --- a/Projects/UOContent/Items/Armor/BaseArmor.Migrations.cs +++ b/Projects/UOContent/Items/Armor/BaseArmor.Migrations.cs @@ -1,3 +1,4 @@ +using System; using AMA = Server.Items.ArmorMeditationAllowance; namespace Server.Items; @@ -192,4 +193,37 @@ public partial class BaseArmor PlayerConstructed = GetSaveFlag(flags, OldSaveFlag.PlayerConstructed); } + + private static bool GetSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0; + + [Flags] + private enum OldSaveFlag + { + None = 0x00000000, + Attributes = 0x00000001, + ArmorAttributes = 0x00000002, + PhysicalBonus = 0x00000004, + FireBonus = 0x00000008, + ColdBonus = 0x00000010, + PoisonBonus = 0x00000020, + EnergyBonus = 0x00000040, + Identified = 0x00000080, + MaxHitPoints = 0x00000100, + HitPoints = 0x00000200, + Crafter = 0x00000400, + Quality = 0x00000800, + Durability = 0x00001000, + Protection = 0x00002000, + Resource = 0x00004000, + BaseArmor = 0x00008000, + StrBonus = 0x00010000, + DexBonus = 0x00020000, + IntBonus = 0x00040000, + StrReq = 0x00080000, + DexReq = 0x00100000, + IntReq = 0x00200000, + MedAllowance = 0x00400000, + SkillBonuses = 0x00800000, + PlayerConstructed = 0x01000000 + } } diff --git a/Projects/UOContent/Items/Armor/BaseArmor.cs b/Projects/UOContent/Items/Armor/BaseArmor.cs index f8c8c02bf..6f91f3a71 100644 --- a/Projects/UOContent/Items/Armor/BaseArmor.cs +++ b/Projects/UOContent/Items/Armor/BaseArmor.cs @@ -1018,8 +1018,6 @@ namespace Server.Items (Parent as Mobile)?.Delta(MobileDelta.Armor); // Tell them armor rating has changed } - private static bool GetSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0; - [AfterDeserialization] private void AfterDeserialization() { @@ -1506,35 +1504,5 @@ namespace Server.Items }; } - [Flags] - private enum OldSaveFlag - { - None = 0x00000000, - Attributes = 0x00000001, - ArmorAttributes = 0x00000002, - PhysicalBonus = 0x00000004, - FireBonus = 0x00000008, - ColdBonus = 0x00000010, - PoisonBonus = 0x00000020, - EnergyBonus = 0x00000040, - Identified = 0x00000080, - MaxHitPoints = 0x00000100, - HitPoints = 0x00000200, - Crafter = 0x00000400, - Quality = 0x00000800, - Durability = 0x00001000, - Protection = 0x00002000, - Resource = 0x00004000, - BaseArmor = 0x00008000, - StrBonus = 0x00010000, - DexBonus = 0x00020000, - IntBonus = 0x00040000, - StrReq = 0x00080000, - DexReq = 0x00100000, - IntReq = 0x00200000, - MedAllowance = 0x00400000, - SkillBonuses = 0x00800000, - PlayerConstructed = 0x01000000 - } } } diff --git a/Projects/UOContent/Items/Clothing/BaseClothing.Migrations.cs b/Projects/UOContent/Items/Clothing/BaseClothing.Migrations.cs index 1c5a22506..7c431f076 100644 --- a/Projects/UOContent/Items/Clothing/BaseClothing.Migrations.cs +++ b/Projects/UOContent/Items/Clothing/BaseClothing.Migrations.cs @@ -1,3 +1,5 @@ +using System; + namespace Server.Items; public partial class BaseClothing @@ -101,4 +103,23 @@ public partial class BaseClothing PlayerConstructed = GetSaveFlag(flags, OldSaveFlag.PlayerConstructed); } + + private static bool GetSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0; + + [Flags] + private enum OldSaveFlag + { + None = 0x00000000, + Resource = 0x00000001, + Attributes = 0x00000002, + ClothingAttributes = 0x00000004, + SkillBonuses = 0x00000008, + Resistances = 0x00000010, + MaxHitPoints = 0x00000020, + HitPoints = 0x00000040, + PlayerConstructed = 0x00000080, + Crafter = 0x00000100, + Quality = 0x00000200, + StrReq = 0x00000400 + } } diff --git a/Projects/UOContent/Items/Clothing/BaseClothing.cs b/Projects/UOContent/Items/Clothing/BaseClothing.cs index 7a699c4a9..8246c8c46 100644 --- a/Projects/UOContent/Items/Clothing/BaseClothing.cs +++ b/Projects/UOContent/Items/Clothing/BaseClothing.cs @@ -880,8 +880,6 @@ namespace Server.Items InvalidateProperties(); } - private static bool GetSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0; - [AfterDeserialization] private void AfterDeserialization() { @@ -902,21 +900,5 @@ namespace Server.Items } } - [Flags] - private enum OldSaveFlag - { - None = 0x00000000, - Resource = 0x00000001, - Attributes = 0x00000002, - ClothingAttributes = 0x00000004, - SkillBonuses = 0x00000008, - Resistances = 0x00000010, - MaxHitPoints = 0x00000020, - HitPoints = 0x00000040, - PlayerConstructed = 0x00000080, - Crafter = 0x00000100, - Quality = 0x00000200, - StrReq = 0x00000400 - } } } diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.Migrations.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.Migrations.cs index 98abd7aad..3385598d9 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.Migrations.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.Migrations.cs @@ -1,3 +1,4 @@ +using System; using Server.Engines.Craft; namespace Server.Items; @@ -39,4 +40,272 @@ public partial class BaseWeapon _aosElementDamages = content.AosElementDamages ?? AosElementAttributesDefaultValue(); _engravedText = content.EngravedText; } + + // Version 9 (pre-codegen) + private void Deserialize(IGenericReader reader, int version) + { + var flags = (OldSaveFlag)reader.ReadInt(); + + if (GetSaveFlag(flags, OldSaveFlag.DamageLevel)) + { + _damageLevel = (WeaponDamageLevel)reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.AccuracyLevel)) + { + _accuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.DurabilityLevel)) + { + _durabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.Quality)) + { + _quality = (WeaponQuality)reader.ReadInt(); + } + else + { + _quality = WeaponQuality.Regular; + } + + if (GetSaveFlag(flags, OldSaveFlag.Hits)) + { + _hitPoints = reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.MaxHits)) + { + _maxHitPoints = reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.Slayer)) + { + _slayer = (SlayerName)reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.Poison)) + { + _poison = reader.ReadPoison(); + } + + if (GetSaveFlag(flags, OldSaveFlag.PoisonCharges)) + { + _poisonCharges = reader.ReadInt(); + } + + if (GetSaveFlag(flags, OldSaveFlag.Crafter)) + { + Timer.DelayCall(crafter => _crafter = crafter?.RawName, reader.ReadEntity()); + } + + if (GetSaveFlag(flags, OldSaveFlag.Identified)) + { + _identified = version >= 6 || reader.ReadBool(); + } + + if (GetSaveFlag(flags, OldSaveFlag.StrReq)) + { + _strRequirement = reader.ReadInt(); + } + else + { + _strRequirement = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.DexReq)) + { + _dexRequirement = reader.ReadInt(); + } + else + { + _dexRequirement = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.IntReq)) + { + _intRequirement = reader.ReadInt(); + } + else + { + _intRequirement = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.MinDamage)) + { + _minDamage = reader.ReadInt(); + } + else + { + _minDamage = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.MaxDamage)) + { + _maxDamage = reader.ReadInt(); + } + else + { + _maxDamage = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.HitSound)) + { + _hitSound = reader.ReadInt(); + } + else + { + _hitSound = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.MissSound)) + { + _missSound = reader.ReadInt(); + } + else + { + _missSound = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.Speed)) + { + if (version < 9) + { + _speed = reader.ReadInt(); + } + else + { + _speed = reader.ReadFloat(); + } + } + else + { + _speed = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.MaxRange)) + { + _maxRange = reader.ReadInt(); + } + else + { + _maxRange = -1; + } + + if (GetSaveFlag(flags, OldSaveFlag.Skill)) + { + _skill = (SkillName)reader.ReadInt(); + } + else + { + _skill = (SkillName)(-1); + } + + if (GetSaveFlag(flags, OldSaveFlag.Type)) + { + _type = (WeaponType)reader.ReadInt(); + } + else + { + _type = (WeaponType)(-1); + } + + if (GetSaveFlag(flags, OldSaveFlag.Animation)) + { + _animation = (WeaponAnimation)reader.ReadInt(); + } + else + { + _animation = (WeaponAnimation)(-1); + } + + if (GetSaveFlag(flags, OldSaveFlag.Resource)) + { + _resource = (CraftResource)reader.ReadInt(); + } + else + { + _resource = CraftResource.Iron; + } + + Attributes = new AosAttributes(this); + + if (GetSaveFlag(flags, OldSaveFlag.Attributes)) + { + Attributes.Deserialize(reader); + } + + WeaponAttributes = new AosWeaponAttributes(this); + + if (GetSaveFlag(flags, OldSaveFlag.WeaponAttributes)) + { + WeaponAttributes.Deserialize(reader); + } + + PlayerConstructed = GetSaveFlag(flags, OldSaveFlag.PlayerConstructed); + + SkillBonuses = new AosSkillBonuses(this); + + if (GetSaveFlag(flags, OldSaveFlag.SkillBonuses)) + { + SkillBonuses.Deserialize(reader); + } + + if (GetSaveFlag(flags, OldSaveFlag.Slayer2)) + { + _slayer2 = (SlayerName)reader.ReadInt(); + } + + AosElementDamages = new AosElementAttributes(this); + + if (GetSaveFlag(flags, OldSaveFlag.ElementalDamages)) + { + AosElementDamages.Deserialize(reader); + } + + if (GetSaveFlag(flags, OldSaveFlag.EngravedText)) + { + _engravedText = reader.ReadString(); + } + } + + private static bool GetSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0; + + [Flags] + private enum OldSaveFlag + { + None = 0x00000000, + DamageLevel = 0x00000001, + AccuracyLevel = 0x00000002, + DurabilityLevel = 0x00000004, + Quality = 0x00000008, + Hits = 0x00000010, + MaxHits = 0x00000020, + Slayer = 0x00000040, + Poison = 0x00000080, + PoisonCharges = 0x00000100, + Crafter = 0x00000200, + Identified = 0x00000400, + StrReq = 0x00000800, + DexReq = 0x00001000, + IntReq = 0x00002000, + MinDamage = 0x00004000, + MaxDamage = 0x00008000, + HitSound = 0x00010000, + MissSound = 0x00020000, + Speed = 0x00040000, + MaxRange = 0x00080000, + Skill = 0x00100000, + Type = 0x00200000, + Animation = 0x00400000, + Resource = 0x00800000, + Attributes = 0x01000000, + WeaponAttributes = 0x02000000, + PlayerConstructed = 0x04000000, + SkillBonuses = 0x08000000, + Slayer2 = 0x10000000, + ElementalDamages = 0x20000000, + EngravedText = 0x40000000 + } } diff --git a/Projects/UOContent/Items/Weapons/BaseWeapon.cs b/Projects/UOContent/Items/Weapons/BaseWeapon.cs index 6aad89d60..1f03daf63 100644 --- a/Projects/UOContent/Items/Weapons/BaseWeapon.cs +++ b/Projects/UOContent/Items/Weapons/BaseWeapon.cs @@ -3571,236 +3571,6 @@ public abstract partial class BaseWeapon } } - private static bool GetSaveFlag(OldSaveFlag flags, OldSaveFlag toGet) => (flags & toGet) != 0; - - private void Deserialize(IGenericReader reader, int version) - { - var flags = (OldSaveFlag)reader.ReadInt(); - - if (GetSaveFlag(flags, OldSaveFlag.DamageLevel)) - { - _damageLevel = (WeaponDamageLevel)reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.AccuracyLevel)) - { - _accuracyLevel = (WeaponAccuracyLevel)reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.DurabilityLevel)) - { - _durabilityLevel = (WeaponDurabilityLevel)reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.Quality)) - { - _quality = (WeaponQuality)reader.ReadInt(); - } - else - { - _quality = WeaponQuality.Regular; - } - - if (GetSaveFlag(flags, OldSaveFlag.Hits)) - { - _hitPoints = reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.MaxHits)) - { - _maxHitPoints = reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.Slayer)) - { - _slayer = (SlayerName)reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.Poison)) - { - _poison = reader.ReadPoison(); - } - - if (GetSaveFlag(flags, OldSaveFlag.PoisonCharges)) - { - _poisonCharges = reader.ReadInt(); - } - - if (GetSaveFlag(flags, OldSaveFlag.Crafter)) - { - Timer.DelayCall(crafter => _crafter = crafter?.RawName, reader.ReadEntity()); - } - - if (GetSaveFlag(flags, OldSaveFlag.Identified)) - { - _identified = version >= 6 || reader.ReadBool(); - } - - if (GetSaveFlag(flags, OldSaveFlag.StrReq)) - { - _strRequirement = reader.ReadInt(); - } - else - { - _strRequirement = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.DexReq)) - { - _dexRequirement = reader.ReadInt(); - } - else - { - _dexRequirement = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.IntReq)) - { - _intRequirement = reader.ReadInt(); - } - else - { - _intRequirement = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.MinDamage)) - { - _minDamage = reader.ReadInt(); - } - else - { - _minDamage = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.MaxDamage)) - { - _maxDamage = reader.ReadInt(); - } - else - { - _maxDamage = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.HitSound)) - { - _hitSound = reader.ReadInt(); - } - else - { - _hitSound = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.MissSound)) - { - _missSound = reader.ReadInt(); - } - else - { - _missSound = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.Speed)) - { - if (version < 9) - { - _speed = reader.ReadInt(); - } - else - { - _speed = reader.ReadFloat(); - } - } - else - { - _speed = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.MaxRange)) - { - _maxRange = reader.ReadInt(); - } - else - { - _maxRange = -1; - } - - if (GetSaveFlag(flags, OldSaveFlag.Skill)) - { - _skill = (SkillName)reader.ReadInt(); - } - else - { - _skill = (SkillName)(-1); - } - - if (GetSaveFlag(flags, OldSaveFlag.Type)) - { - _type = (WeaponType)reader.ReadInt(); - } - else - { - _type = (WeaponType)(-1); - } - - if (GetSaveFlag(flags, OldSaveFlag.Animation)) - { - _animation = (WeaponAnimation)reader.ReadInt(); - } - else - { - _animation = (WeaponAnimation)(-1); - } - - if (GetSaveFlag(flags, OldSaveFlag.Resource)) - { - _resource = (CraftResource)reader.ReadInt(); - } - else - { - _resource = CraftResource.Iron; - } - - Attributes = new AosAttributes(this); - - if (GetSaveFlag(flags, OldSaveFlag.Attributes)) - { - Attributes.Deserialize(reader); - } - - WeaponAttributes = new AosWeaponAttributes(this); - - if (GetSaveFlag(flags, OldSaveFlag.WeaponAttributes)) - { - WeaponAttributes.Deserialize(reader); - } - - PlayerConstructed = GetSaveFlag(flags, OldSaveFlag.PlayerConstructed); - - SkillBonuses = new AosSkillBonuses(this); - - if (GetSaveFlag(flags, OldSaveFlag.SkillBonuses)) - { - SkillBonuses.Deserialize(reader); - } - - if (GetSaveFlag(flags, OldSaveFlag.Slayer2)) - { - _slayer2 = (SlayerName)reader.ReadInt(); - } - - AosElementDamages = new AosElementAttributes(this); - - if (GetSaveFlag(flags, OldSaveFlag.ElementalDamages)) - { - AosElementDamages.Deserialize(reader); - } - - if (GetSaveFlag(flags, OldSaveFlag.EngravedText)) - { - _engravedText = reader.ReadString(); - } - } - [AfterDeserialization] private void AfterDeserialization() { @@ -3866,42 +3636,6 @@ public abstract partial class BaseWeapon } } - [Flags] - private enum OldSaveFlag - { - None = 0x00000000, - DamageLevel = 0x00000001, - AccuracyLevel = 0x00000002, - DurabilityLevel = 0x00000004, - Quality = 0x00000008, - Hits = 0x00000010, - MaxHits = 0x00000020, - Slayer = 0x00000040, - Poison = 0x00000080, - PoisonCharges = 0x00000100, - Crafter = 0x00000200, - Identified = 0x00000400, - StrReq = 0x00000800, - DexReq = 0x00001000, - IntReq = 0x00002000, - MinDamage = 0x00004000, - MaxDamage = 0x00008000, - HitSound = 0x00010000, - MissSound = 0x00020000, - Speed = 0x00040000, - MaxRange = 0x00080000, - Skill = 0x00100000, - Type = 0x00200000, - Animation = 0x00400000, - Resource = 0x00800000, - Attributes = 0x01000000, - WeaponAttributes = 0x02000000, - PlayerConstructed = 0x04000000, - SkillBonuses = 0x08000000, - Slayer2 = 0x10000000, - ElementalDamages = 0x20000000, - EngravedText = 0x40000000 - } } public enum CheckSlayerResult