feat(castle-siege): adopt the upstream Castle Siege data model and persistence

Brings in the database layer of upstream OpenMU PRs #754 and #860 without
touching AdaMu's working Castle Siege gameplay. This is purely additive: the
existing 5-phase implementation still runs exactly as before.

What is included:

- DataModel: CastleSiegeState (the original Season 6 values 0-9, which are
  exactly what the game client's CASTLESIEGE_STATE enum expects),
  CastleSiegeJoinSide, and the zone/NPC/upgrade definition types.
- Entities: CastleSiegeData, CastleSiegeGuildRegistration, CastleSiegeNpcState.
  These identify a guild by its persistent Guid rather than by name.
- Generated persistence: 8 BasicModel + 8 EntityFramework model classes,
  CastleSiegeExtensions, and the regenerated ExtendedTypeContext,
  MapsterConfigurator and GameConfiguration partials.
- Migrations: 20260730194321_AddCastleSiege and
  20260801162427_ConfigureCastleSiegePersistence, plus the model snapshot.
- EntityDataContext gains the two DbSets and the five model registrations.
- EntityFrameworkContextBase only publishes configuration changes for entities
  in the configuration schema, so siege state writes are no longer broadcast as
  configuration changes.

AdaMu-specific adaptations:

- UpdateVersion.AddCastleSiegeData is 105, not upstream's 100. AdaMu already
  ships 95-104, and the applied-update bookkeeping is keyed on this value, so a
  collision would skip or re-run updates on live databases.
- CastleSiegeInitializer does not seed a weekly StateSchedule. Upstream drives
  the cycle from a fixed Saturday schedule; AdaMu drives it manually from
  CastleSiegeEventPlugIn and the AdminPanel, so the schedule is left empty and
  nothing reads it.

The seeded NPC definitions match AdaMu's existing hard-coded coordinates
exactly (6 gates, the two crown switches and the crown), and additionally
provide 4 guardian statues, 6 guardsmen and real gate/statue hit point tables
that the current implementation does not have yet.

Two pre-existing migrations were restyled by upstream (copyright header, using
placement, trailing comma). No functional change.

Verified: full server build succeeds with 0 errors.
This commit is contained in:
Acentech Dev
2026-08-04 03:28:10 +03:00
parent 0fdb455cec
commit 3aa9815b10
42 changed files with 15383 additions and 7 deletions

View File

@@ -0,0 +1,152 @@
// <copyright file="CastleSiegeConfiguration.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Annotations;
using MUnique.OpenMU.DataModel.Configuration.Items;
/// <summary>
/// Main configuration for the castle siege event.
/// </summary>
[Cloneable]
public partial class CastleSiegeConfiguration
{
/// <summary>
/// Gets or sets a value indicating whether the castle siege feature is enabled.
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets the number of seconds a guild must hold the crown to capture the castle.
/// </summary>
public int CrownHoldTimeSeconds { get; set; } = 30;
/// <summary>
/// Gets or sets the minimum combined level of a guild master required to register for the siege.
/// </summary>
public int RegisterMinLevel { get; set; } = 200;
/// <summary>
/// Gets or sets the minimum number of guild members required to register for the siege.
/// </summary>
public int RegisterMinMembers { get; set; } = 20;
/// <summary>
/// Gets or sets the minimum number of seconds a participant must be present in the battle to be eligible for a reward.
/// </summary>
public int ParticipantRewardMinSeconds { get; set; }
/// <summary>
/// Gets or sets the maximum number of attacking alliance slots.
/// </summary>
public int MaxAttackingGuilds { get; set; } = 3;
/// <summary>
/// Gets or sets the guild score awarded to the guild that wins the siege.
/// </summary>
public int GuildScoreCastleSiege { get; set; }
/// <summary>
/// Gets or sets the guild score awarded to alliance member guilds of the winning side.
/// </summary>
public int GuildScoreCastleSiegeMembers { get; set; }
/// <summary>
/// Gets or sets the Zen cost for the castle owner to re-purchase a destroyed gate.
/// </summary>
public int GateBuyPrice { get; set; }
/// <summary>
/// Gets or sets the Zen cost for the castle owner to re-purchase a destroyed statue.
/// </summary>
public int StatueBuyPrice { get; set; }
/// <summary>
/// Gets or sets the map definition for the Valley of Loren (map 30), where the siege takes place.
/// </summary>
public virtual GameMapDefinition? CastleSiegeMapDefinition { get; set; }
/// <summary>
/// Gets or sets the map definition for the Land of Trials (map 31), the castle-owner's exclusive zone.
/// </summary>
public virtual GameMapDefinition? LandOfTrialsMapDefinition { get; set; }
/// <summary>
/// Gets or sets the item definition for the participation reward item.
/// </summary>
public virtual ItemDefinition? RewardItemDefinition { get; set; }
/// <summary>
/// Gets or sets the schedule entries that define when each siege state begins.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeStateScheduleEntry> StateSchedule { get; protected set; } = null!;
/// <summary>
/// Gets or sets the definitions for all castle siege NPCs (gates, statues, etc.).
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeNpcDefinition> NpcDefinitions { get; protected set; } = null!;
/// <summary>
/// Gets or sets the upgrade levels for gate defense.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeUpgradeDefinition> GateDefenseUpgrades { get; protected set; } = null!;
/// <summary>
/// Gets or sets the upgrade levels for gate maximum HP.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeUpgradeDefinition> GateLifeUpgrades { get; protected set; } = null!;
/// <summary>
/// Gets or sets the upgrade levels for statue defense.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeUpgradeDefinition> StatueDefenseUpgrades { get; protected set; } = null!;
/// <summary>
/// Gets or sets the upgrade levels for statue maximum HP.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeUpgradeDefinition> StatueLifeUpgrades { get; protected set; } = null!;
/// <summary>
/// Gets or sets the upgrade levels for statue HP regeneration.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeUpgradeDefinition> StatueRegenUpgrades { get; protected set; } = null!;
/// <summary>
/// Gets or sets the zones on the siege map where attacking siege machines may be placed.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeZoneDefinition> AttackMachineZones { get; protected set; } = null!;
/// <summary>
/// Gets or sets the zones on the siege map where defensive siege machines may be placed.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeZoneDefinition> DefenseMachineZones { get; protected set; } = null!;
/// <summary>
/// Gets or sets the zone where defending players respawn during the siege.
/// </summary>
[MemberOfAggregate]
public virtual CastleSiegeZoneDefinition? DefenseRespawnArea { get; set; }
/// <summary>
/// Gets or sets the zone where attacking players respawn during the siege.
/// </summary>
[MemberOfAggregate]
public virtual CastleSiegeZoneDefinition? AttackRespawnArea { get; set; }
/// <inheritdoc />
public override string ToString()
{
return "Castle Siege Configuration";
}
}

View File

@@ -0,0 +1,36 @@
// <copyright file="CastleSiegeJoinSide.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
/// <summary>
/// Defines the side (defending or attacking) a guild or NPC belongs to in the castle siege.
/// </summary>
public enum CastleSiegeJoinSide : byte
{
/// <summary>
/// No side assigned.
/// </summary>
None = 0,
/// <summary>
/// The defending guild side.
/// </summary>
Defense = 1,
/// <summary>
/// The first attacking alliance slot.
/// </summary>
Attack1 = 2,
/// <summary>
/// The second attacking alliance slot.
/// </summary>
Attack2 = 3,
/// <summary>
/// The third attacking alliance slot.
/// </summary>
Attack3 = 4,
}

View File

@@ -0,0 +1,55 @@
// <copyright file="CastleSiegeNpcDefinition.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Annotations;
/// <summary>
/// Defines a castle siege NPC instance, including its spawn location, side, and persistence settings.
/// </summary>
[Cloneable]
public partial class CastleSiegeNpcDefinition
{
/// <summary>
/// Gets or sets the monster definition template for this NPC.
/// </summary>
public virtual MonsterDefinition? MonsterDefinition { get; set; }
/// <summary>
/// Gets or sets the unique instance identifier within its NPC type.
/// </summary>
public byte InstanceId { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this NPC's state is persisted to the database between sieges.
/// </summary>
public bool IsPersistedToDatabase { get; set; }
/// <summary>
/// Gets or sets the default join side this NPC belongs to.
/// </summary>
public CastleSiegeJoinSide DefaultSide { get; set; }
/// <summary>
/// Gets or sets the X coordinate of the NPC's spawn position.
/// </summary>
public byte SpawnX { get; set; }
/// <summary>
/// Gets or sets the Y coordinate of the NPC's spawn position.
/// </summary>
public byte SpawnY { get; set; }
/// <summary>
/// Gets or sets the facing direction of the NPC at spawn.
/// </summary>
public Direction Direction { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"{this.MonsterDefinition} #{this.InstanceId} at ({this.SpawnX},{this.SpawnY})";
}
}

View File

@@ -0,0 +1,61 @@
// <copyright file="CastleSiegeState.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
/// <summary>
/// The state of the castle siege event cycle.
/// </summary>
public enum CastleSiegeState : byte
{
/// <summary>
/// Idle state before guild registration opens.
/// </summary>
Idle1 = 0,
/// <summary>
/// Guilds may register for the siege.
/// </summary>
RegisterGuild = 1,
/// <summary>
/// Idle state after guild registration.
/// </summary>
Idle2 = 2,
/// <summary>
/// Guilds may register emblems (Marks of Lord) to determine the attacking guilds.
/// </summary>
RegisterMark = 3,
/// <summary>
/// Idle state after mark registration.
/// </summary>
Idle3 = 4,
/// <summary>
/// Players are notified that the siege is about to start.
/// </summary>
Notify = 5,
/// <summary>
/// The siege map is prepared and entry is allowed.
/// </summary>
Ready = 6,
/// <summary>
/// The siege battle is in progress.
/// </summary>
Start = 7,
/// <summary>
/// The siege battle has ended and results are being processed.
/// </summary>
End = 8,
/// <summary>
/// The full siege cycle has completed.
/// </summary>
EndCycle = 9,
}

View File

@@ -0,0 +1,40 @@
// <copyright file="CastleSiegeStateScheduleEntry.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Annotations;
/// <summary>
/// Defines a scheduled transition to a specific <see cref="CastleSiegeState"/> at a given day and time.
/// </summary>
[Cloneable]
public partial class CastleSiegeStateScheduleEntry
{
/// <summary>
/// Gets or sets the siege state that becomes active at the scheduled time.
/// </summary>
public CastleSiegeState State { get; set; }
/// <summary>
/// Gets or sets the day of the week on which this state transition occurs.
/// </summary>
public DayOfWeek DayOfWeek { get; set; }
/// <summary>
/// Gets or sets the hour (023) at which this state transition occurs.
/// </summary>
public byte Hour { get; set; }
/// <summary>
/// Gets or sets the minute (059) at which this state transition occurs.
/// </summary>
public byte Minute { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"{this.State} on {this.DayOfWeek} at {this.Hour:D2}:{this.Minute:D2}";
}
}

View File

@@ -0,0 +1,40 @@
// <copyright file="CastleSiegeUpgradeDefinition.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Annotations;
/// <summary>
/// Defines one level of an upgrade that the castle owner can apply to a gate or statue NPC.
/// </summary>
[Cloneable]
public partial class CastleSiegeUpgradeDefinition
{
/// <summary>
/// Gets or sets the upgrade level (03), where 0 represents the base/unupgraded state.
/// </summary>
public byte Level { get; set; }
/// <summary>
/// Gets or sets the number of Jewels of Guardian required to perform this upgrade.
/// </summary>
public int RequiredJewelOfGuardianCount { get; set; }
/// <summary>
/// Gets or sets the amount of Zen required to perform this upgrade.
/// </summary>
public int RequiredZen { get; set; }
/// <summary>
/// Gets or sets the resulting stat value granted by this upgrade level (defense or max HP).
/// </summary>
public int Value { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"Level {this.Level}: Value={this.Value}, Jewels={this.RequiredJewelOfGuardianCount}, Zen={this.RequiredZen}";
}
}

View File

@@ -0,0 +1,31 @@
// <copyright file="CastleSiegeUpgradeType.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
/// <summary>
/// The type of upgrade applied to a castle siege NPC (gate or statue).
/// </summary>
public enum CastleSiegeUpgradeType : byte
{
/// <summary>
/// No upgrade type assigned.
/// </summary>
Undefined = 0,
/// <summary>
/// Increases the defense stat of the NPC.
/// </summary>
Defense = 1,
/// <summary>
/// Increases the HP regeneration rate of the NPC.
/// </summary>
Regen = 2,
/// <summary>
/// Increases the maximum HP of the NPC.
/// </summary>
Life = 3,
}

View File

@@ -0,0 +1,40 @@
// <copyright file="CastleSiegeZoneDefinition.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.Annotations;
/// <summary>
/// Defines a rectangular zone on the castle siege map, used for spawn areas and machine zones.
/// </summary>
[Cloneable]
public partial class CastleSiegeZoneDefinition
{
/// <summary>
/// Gets or sets the top-left X coordinate of the zone.
/// </summary>
public byte X1 { get; set; }
/// <summary>
/// Gets or sets the top-left Y coordinate of the zone.
/// </summary>
public byte Y1 { get; set; }
/// <summary>
/// Gets or sets the bottom-right X coordinate of the zone.
/// </summary>
public byte X2 { get; set; }
/// <summary>
/// Gets or sets the bottom-right Y coordinate of the zone.
/// </summary>
public byte Y2 { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"{this.X1} / {this.Y1} to {this.X2} / {this.Y2}";
}
}

View File

@@ -300,6 +300,12 @@ public partial class GameConfiguration
[MemberOfAggregate]
public virtual ICollection<MiniGameDefinition> MiniGameDefinitions { get; protected set; } = null!;
/// <summary>
/// Gets or sets the castle siege configuration.
/// </summary>
[MemberOfAggregate]
public virtual CastleSiegeConfiguration? CastleSiegeConfiguration { get; set; }
/// <inheritdoc />
public override string ToString()
{

View File

@@ -0,0 +1,67 @@
// <copyright file="CastleSiegeData.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Entities;
/// <summary>
/// Persistent state of the castle siege, stored as a single row across siege cycles.
/// </summary>
[AggregateRoot]
public class CastleSiegeData
{
/// <summary>
/// Gets or sets the unique identifier of this record.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the persistent identifier of the guild that currently owns the castle.
/// <see langword="null"/> when no guild owns the castle.
/// </summary>
public Guid? OwnerGuildId { get; set; }
/// <summary>
/// Gets or sets a value indicating whether any guild currently occupies the castle.
/// </summary>
public bool IsOccupied { get; set; }
/// <summary>
/// Gets or sets the Chaos Machine tax rate applied by the castle owner (03).
/// </summary>
public byte TaxChaos { get; set; }
/// <summary>
/// Gets or sets the personal store tax rate applied by the castle owner (03).
/// </summary>
public byte TaxStore { get; set; }
/// <summary>
/// Gets or sets the entry fee (in Zen) for the castle owner's hunt zone (0300000).
/// </summary>
public int TaxHunt { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the hunt zone (Land of Trials) is currently open to the public.
/// </summary>
public bool IsHuntZoneEnabled { get; set; }
/// <summary>
/// Gets or sets the accumulated tribute money collected from the hunt zone and taxes.
/// </summary>
public long TributeMoney { get; set; }
/// <summary>
/// Gets or sets the persisted states of all castle NPCs.
/// </summary>
[MemberOfAggregate]
public virtual ICollection<CastleSiegeNpcState> NpcStates { get; protected set; } = null!;
/// <inheritdoc />
public override string ToString()
{
return this.IsOccupied
? $"Castle owned by guild {this.OwnerGuildId}"
: "Castle unoccupied";
}
}

View File

@@ -0,0 +1,44 @@
// <copyright file="CastleSiegeGuildRegistration.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Entities;
/// <summary>
/// Stores a guild's registration data for the current castle siege cycle,
/// including the number of emblems submitted to determine attacking guilds.
/// </summary>
[AggregateRoot]
public class CastleSiegeGuildRegistration
{
/// <summary>
/// Gets or sets the unique identifier of this registration record.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the persistent identifier of the registered guild.
/// </summary>
public Guid GuildId { get; set; }
/// <summary>
/// Gets or sets the guild name, denormalized for convenience to avoid extra lookups during siege processing.
/// </summary>
public string GuildName { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the number of Emblems of Lord registered by this guild.
/// </summary>
public int Marks { get; set; }
/// <summary>
/// Gets or sets the insertion order of this registration, used for tie-breaking when guilds have equal marks.
/// </summary>
public int RegistrationOrder { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"{this.GuildName} (Marks={this.Marks}, Order={this.RegistrationOrder})";
}
}

View File

@@ -0,0 +1,52 @@
// <copyright file="CastleSiegeNpcState.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.DataModel.Entities;
/// <summary>
/// Persistent state of a single castle siege NPC between siege cycles.
/// </summary>
public class CastleSiegeNpcState
{
/// <summary>
/// Gets or sets the unique identifier of this NPC state.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the monster definition number that identifies the NPC template.
/// </summary>
public short MonsterNumber { get; set; }
/// <summary>
/// Gets or sets the instance identifier matching <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition.InstanceId"/>.
/// </summary>
public byte InstanceId { get; set; }
/// <summary>
/// Gets or sets the current defense upgrade level (03).
/// </summary>
public byte DefenseLevel { get; set; }
/// <summary>
/// Gets or sets the current HP regeneration upgrade level (03).
/// </summary>
public byte RegenLevel { get; set; }
/// <summary>
/// Gets or sets the current maximum HP upgrade level (03).
/// </summary>
public byte LifeLevel { get; set; }
/// <summary>
/// Gets or sets the current HP of the NPC. A value of 0 means the NPC is destroyed.
/// </summary>
public int CurrentHp { get; set; }
/// <inheritdoc />
public override string ToString()
{
return $"NPC {this.MonsterNumber} #{this.InstanceId} (HP={this.CurrentHp})";
}
}

View File

@@ -0,0 +1,342 @@
// <copyright file="CastleSiegeConfiguration.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeConfiguration"/>.
/// </summary>
public partial class CastleSiegeConfiguration : MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration, IIdentifiable, IConvertibleTo<CastleSiegeConfiguration>
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets the raw collection of <see cref="StateSchedule" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("stateSchedule")]
public ICollection<CastleSiegeStateScheduleEntry> RawStateSchedule { get; } = new List<CastleSiegeStateScheduleEntry>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry> StateSchedule
{
get => base.StateSchedule ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry, CastleSiegeStateScheduleEntry>(this.RawStateSchedule);
protected set
{
this.StateSchedule.Clear();
foreach (var item in value)
{
this.StateSchedule.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="NpcDefinitions" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("npcDefinitions")]
public ICollection<CastleSiegeNpcDefinition> RawNpcDefinitions { get; } = new List<CastleSiegeNpcDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition> NpcDefinitions
{
get => base.NpcDefinitions ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition, CastleSiegeNpcDefinition>(this.RawNpcDefinitions);
protected set
{
this.NpcDefinitions.Clear();
foreach (var item in value)
{
this.NpcDefinitions.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="GateDefenseUpgrades" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("gateDefenseUpgrades")]
public ICollection<CastleSiegeUpgradeDefinition> RawGateDefenseUpgrades { get; } = new List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> GateDefenseUpgrades
{
get => base.GateDefenseUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawGateDefenseUpgrades);
protected set
{
this.GateDefenseUpgrades.Clear();
foreach (var item in value)
{
this.GateDefenseUpgrades.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="GateLifeUpgrades" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("gateLifeUpgrades")]
public ICollection<CastleSiegeUpgradeDefinition> RawGateLifeUpgrades { get; } = new List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> GateLifeUpgrades
{
get => base.GateLifeUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawGateLifeUpgrades);
protected set
{
this.GateLifeUpgrades.Clear();
foreach (var item in value)
{
this.GateLifeUpgrades.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="StatueDefenseUpgrades" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("statueDefenseUpgrades")]
public ICollection<CastleSiegeUpgradeDefinition> RawStatueDefenseUpgrades { get; } = new List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> StatueDefenseUpgrades
{
get => base.StatueDefenseUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawStatueDefenseUpgrades);
protected set
{
this.StatueDefenseUpgrades.Clear();
foreach (var item in value)
{
this.StatueDefenseUpgrades.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="StatueLifeUpgrades" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("statueLifeUpgrades")]
public ICollection<CastleSiegeUpgradeDefinition> RawStatueLifeUpgrades { get; } = new List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> StatueLifeUpgrades
{
get => base.StatueLifeUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawStatueLifeUpgrades);
protected set
{
this.StatueLifeUpgrades.Clear();
foreach (var item in value)
{
this.StatueLifeUpgrades.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="StatueRegenUpgrades" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("statueRegenUpgrades")]
public ICollection<CastleSiegeUpgradeDefinition> RawStatueRegenUpgrades { get; } = new List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> StatueRegenUpgrades
{
get => base.StatueRegenUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawStatueRegenUpgrades);
protected set
{
this.StatueRegenUpgrades.Clear();
foreach (var item in value)
{
this.StatueRegenUpgrades.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="AttackMachineZones" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("attackMachineZones")]
public ICollection<CastleSiegeZoneDefinition> RawAttackMachineZones { get; } = new List<CastleSiegeZoneDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition> AttackMachineZones
{
get => base.AttackMachineZones ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition, CastleSiegeZoneDefinition>(this.RawAttackMachineZones);
protected set
{
this.AttackMachineZones.Clear();
foreach (var item in value)
{
this.AttackMachineZones.Add(item);
}
}
}
/// <summary>
/// Gets the raw collection of <see cref="DefenseMachineZones" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("defenseMachineZones")]
public ICollection<CastleSiegeZoneDefinition> RawDefenseMachineZones { get; } = new List<CastleSiegeZoneDefinition>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition> DefenseMachineZones
{
get => base.DefenseMachineZones ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition, CastleSiegeZoneDefinition>(this.RawDefenseMachineZones);
protected set
{
this.DefenseMachineZones.Clear();
foreach (var item in value)
{
this.DefenseMachineZones.Add(item);
}
}
}
/// <summary>
/// Gets the raw object of <see cref="CastleSiegeMapDefinition" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("castleSiegeMapDefinition")]
public GameMapDefinition RawCastleSiegeMapDefinition
{
get => base.CastleSiegeMapDefinition as GameMapDefinition;
set => base.CastleSiegeMapDefinition = value;
}
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override MUnique.OpenMU.DataModel.Configuration.GameMapDefinition CastleSiegeMapDefinition
{
get => base.CastleSiegeMapDefinition;
set => base.CastleSiegeMapDefinition = value;
}
/// <summary>
/// Gets the raw object of <see cref="LandOfTrialsMapDefinition" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("landOfTrialsMapDefinition")]
public GameMapDefinition RawLandOfTrialsMapDefinition
{
get => base.LandOfTrialsMapDefinition as GameMapDefinition;
set => base.LandOfTrialsMapDefinition = value;
}
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override MUnique.OpenMU.DataModel.Configuration.GameMapDefinition LandOfTrialsMapDefinition
{
get => base.LandOfTrialsMapDefinition;
set => base.LandOfTrialsMapDefinition = value;
}
/// <summary>
/// Gets the raw object of <see cref="RewardItemDefinition" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("rewardItemDefinition")]
public ItemDefinition RawRewardItemDefinition
{
get => base.RewardItemDefinition as ItemDefinition;
set => base.RewardItemDefinition = value;
}
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override MUnique.OpenMU.DataModel.Configuration.Items.ItemDefinition RewardItemDefinition
{
get => base.RewardItemDefinition;
set => base.RewardItemDefinition = value;
}
/// <summary>
/// Gets the raw object of <see cref="DefenseRespawnArea" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("defenseRespawnArea")]
public CastleSiegeZoneDefinition RawDefenseRespawnArea
{
get => base.DefenseRespawnArea as CastleSiegeZoneDefinition;
set => base.DefenseRespawnArea = value;
}
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition DefenseRespawnArea
{
get => base.DefenseRespawnArea;
set => base.DefenseRespawnArea = value;
}
/// <summary>
/// Gets the raw object of <see cref="AttackRespawnArea" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("attackRespawnArea")]
public CastleSiegeZoneDefinition RawAttackRespawnArea
{
get => base.AttackRespawnArea as CastleSiegeZoneDefinition;
set => base.AttackRespawnArea = value;
}
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition AttackRespawnArea
{
get => base.AttackRespawnArea;
set => base.AttackRespawnArea = value;
}
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeConfiguration();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeConfiguration Convert() => this;
}

View File

@@ -0,0 +1,67 @@
// <copyright file="CastleSiegeData.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeData"/>.
/// </summary>
public partial class CastleSiegeData : MUnique.OpenMU.DataModel.Entities.CastleSiegeData, IIdentifiable, IConvertibleTo<CastleSiegeData>
{
/// <summary>
/// Gets the raw collection of <see cref="NpcStates" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("npcStates")]
public ICollection<CastleSiegeNpcState> RawNpcStates { get; } = new List<CastleSiegeNpcState>();
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override ICollection<MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState> NpcStates
{
get => base.NpcStates ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState, CastleSiegeNpcState>(this.RawNpcStates);
protected set
{
this.NpcStates.Clear();
foreach (var item in value)
{
this.NpcStates.Add(item);
}
}
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeData Convert() => this;
}

View File

@@ -0,0 +1,46 @@
// <copyright file="CastleSiegeGuildRegistration.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeGuildRegistration"/>.
/// </summary>
public partial class CastleSiegeGuildRegistration : MUnique.OpenMU.DataModel.Entities.CastleSiegeGuildRegistration, IIdentifiable, IConvertibleTo<CastleSiegeGuildRegistration>
{
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeGuildRegistration Convert() => this;
}

View File

@@ -0,0 +1,81 @@
// <copyright file="CastleSiegeNpcDefinition.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeNpcDefinition"/>.
/// </summary>
public partial class CastleSiegeNpcDefinition : MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition, IIdentifiable, IConvertibleTo<CastleSiegeNpcDefinition>
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets the raw object of <see cref="MonsterDefinition" />.
/// </summary>
[System.Text.Json.Serialization.JsonPropertyName("monsterDefinition")]
public MonsterDefinition RawMonsterDefinition
{
get => base.MonsterDefinition as MonsterDefinition;
set => base.MonsterDefinition = value;
}
/// <inheritdoc/>
[System.Text.Json.Serialization.JsonIgnore]
public override MUnique.OpenMU.DataModel.Configuration.MonsterDefinition MonsterDefinition
{
get => base.MonsterDefinition;
set => base.MonsterDefinition = value;
}
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeNpcDefinition();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeNpcDefinition Convert() => this;
}

View File

@@ -0,0 +1,46 @@
// <copyright file="CastleSiegeNpcState.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeNpcState"/>.
/// </summary>
public partial class CastleSiegeNpcState : MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState, IIdentifiable, IConvertibleTo<CastleSiegeNpcState>
{
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeNpcState Convert() => this;
}

View File

@@ -0,0 +1,63 @@
// <copyright file="CastleSiegeStateScheduleEntry.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeStateScheduleEntry"/>.
/// </summary>
public partial class CastleSiegeStateScheduleEntry : MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry, IIdentifiable, IConvertibleTo<CastleSiegeStateScheduleEntry>
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeStateScheduleEntry();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeStateScheduleEntry Convert() => this;
}

View File

@@ -0,0 +1,63 @@
// <copyright file="CastleSiegeUpgradeDefinition.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeUpgradeDefinition"/>.
/// </summary>
public partial class CastleSiegeUpgradeDefinition : MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, IIdentifiable, IConvertibleTo<CastleSiegeUpgradeDefinition>
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeUpgradeDefinition();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeUpgradeDefinition Convert() => this;
}

View File

@@ -0,0 +1,63 @@
// <copyright file="CastleSiegeZoneDefinition.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.BasicModel;
using MUnique.OpenMU.Persistence.Json;
/// <summary>
/// A plain implementation of <see cref="CastleSiegeZoneDefinition"/>.
/// </summary>
public partial class CastleSiegeZoneDefinition : MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition, IIdentifiable, IConvertibleTo<CastleSiegeZoneDefinition>
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeZoneDefinition();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
/// <inheritdoc/>
public CastleSiegeZoneDefinition Convert() => this;
}

View File

@@ -21,6 +21,16 @@ public class EntityDataContext : ExtendedTypeContext
/// </summary>
internal GameConfiguration? CurrentGameConfiguration { get; set; }
/// <summary>
/// Gets the persistent Castle Siege state.
/// </summary>
internal DbSet<CastleSiegeData> CastleSiegeData => this.Set<CastleSiegeData>();
/// <summary>
/// Gets the Castle Siege guild registrations.
/// </summary>
internal DbSet<CastleSiegeGuildRegistration> CastleSiegeGuildRegistrations => this.Set<CastleSiegeGuildRegistration>();
/// <inheritdoc/>
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
@@ -58,6 +68,11 @@ public class EntityDataContext : ExtendedTypeContext
modelBuilder.Entity<Account>().Apply();
modelBuilder.Entity<Character>().Apply();
modelBuilder.Entity<CharacterClass>().Apply();
modelBuilder.Entity<CastleSiegeConfiguration>().Apply();
modelBuilder.Entity<CastleSiegeData>().Apply();
modelBuilder.Entity<CastleSiegeGuildRegistration>().Apply();
modelBuilder.Entity<CastleSiegeNpcDefinition>().Apply();
modelBuilder.Entity<CastleSiegeNpcState>().Apply();
modelBuilder.Entity<DropItemGroup>().Apply();
modelBuilder.Entity<ExitGate>().Apply();
modelBuilder.Entity<GameConfiguration>().Apply();

View File

@@ -68,6 +68,55 @@ internal class EntityFrameworkContextBase : IContext
/// <inheritdoc/>
public async ValueTask<bool> SaveChangesAsync(CancellationToken cancellationToken = default)
{
// A player's entities can be mutated by game logic on a flow that is not serialized against
// this save (for example item destruction on an attacker's thread during combat). Such a
// concurrent mutation makes change detection throw while it enumerates a tracked collection.
// The mutation is a single, quick operation, so a bounded retry lands on a stable moment
// instead of failing the whole save - which would otherwise leave the session unpersisted and
// roll the player back on relog.
const int maxAttempts = 3;
var attempt = 0;
while (true)
{
attempt++;
try
{
return await this.SaveChangesCoreAsync(cancellationToken).ConfigureAwait(false);
}
catch (Exception ex) when (attempt < maxAttempts && IsTransientConcurrencyConflict(ex))
{
this._logger.LogWarning(ex, "Transient concurrency conflict while saving (attempt {Attempt}/{MaxAttempts}); retrying.", attempt, maxAttempts);
await Task.Delay(attempt * 10, cancellationToken).ConfigureAwait(false);
}
}
}
/// <summary>
/// Determines whether the exception is a transient conflict caused by a concurrent entity mutation
/// racing this save, and is therefore worth retrying.
/// </summary>
/// <param name="exception">The exception thrown by the save.</param>
/// <returns><c>true</c> if the save should be retried.</returns>
private static bool IsTransientConcurrencyConflict(Exception exception)
{
// A concurrent entity mutation racing this save corrupts the change tracker mid-enumeration.
// Depending on exactly where change detection was, it surfaces as one of several types - a
// modified collection (InvalidOperationException), a transiently-null internal key
// (ArgumentNullException/NullReferenceException), or an out-of-range index. All are transient:
// the racing mutation is a single quick operation, so a bounded retry lands on a stable moment.
// A genuinely persistent error of the same type is not masked - it rethrows once the retries
// are exhausted. The deterministic serialization (per-player persistence lock) is the primary
// guard; this retry only needs to absorb the rare, bursty sources that lock isn't held for.
return exception is DbUpdateConcurrencyException
or InvalidOperationException
or ArgumentNullException
or NullReferenceException
or IndexOutOfRangeException
or KeyNotFoundException;
}
private async ValueTask<bool> SaveChangesCoreAsync(CancellationToken cancellationToken)
{
using var l = await this._lock.LockAsync();
@@ -252,6 +301,14 @@ internal class EntityFrameworkContextBase : IContext
GC.SuppressFinalize(this);
}
/// <summary>
/// Determines whether changes of an entity type are published as configuration changes.
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <returns><see langword="true"/> when the entity belongs to the configuration schema.</returns>
internal static bool PublishesConfigurationChanges(IReadOnlyEntityType entityType)
=> entityType.GetSchema() == SchemaNames.Configuration;
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
@@ -343,7 +400,9 @@ internal class EntityFrameworkContextBase : IContext
}
var changedEntries = this.Context.ChangeTracker.Entries()
.Where(entity => entity.State != EntityState.Unchanged).ToList();
.Where(entity => entity.State != EntityState.Unchanged
&& PublishesConfigurationChanges(entity.Metadata))
.ToList();
foreach (var entry in changedEntries)
{
var (parent, parentCollectionNavigation) = this.GetParentInformation(entry);

View File

@@ -0,0 +1,85 @@
// <copyright file="CastleSiegeExtensions.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.EntityFramework.Extensions.ModelBuilder;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using MUnique.OpenMU.Persistence.EntityFramework.Model;
/// <summary>
/// Extensions for Castle Siege-related <see cref="EntityTypeBuilder"/>s.
/// </summary>
internal static class CastleSiegeExtensions
{
/// <summary>
/// Applies the settings for the <see cref="CastleSiegeConfiguration"/> entity.
/// </summary>
/// <param name="builder">The builder.</param>
public static void Apply(this EntityTypeBuilder<CastleSiegeConfiguration> builder)
{
builder.Property(configuration => configuration.CrownHoldTimeSeconds).HasDefaultValue(30);
builder.Property(configuration => configuration.RegisterMinLevel).HasDefaultValue(200);
builder.Property(configuration => configuration.RegisterMinMembers).HasDefaultValue(20);
builder.Property(configuration => configuration.MaxAttackingGuilds).HasDefaultValue(3);
builder.HasOne(configuration => configuration.RawCastleSiegeMapDefinition)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(configuration => configuration.RawLandOfTrialsMapDefinition)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
builder.HasOne(configuration => configuration.RawRewardItemDefinition)
.WithMany()
.OnDelete(DeleteBehavior.Restrict);
}
/// <summary>
/// Applies the settings for the <see cref="CastleSiegeNpcDefinition"/> entity.
/// </summary>
/// <param name="builder">The builder.</param>
public static void Apply(this EntityTypeBuilder<CastleSiegeNpcDefinition> builder)
{
builder.HasOne(definition => definition.RawMonsterDefinition)
.WithMany()
.IsRequired()
.OnDelete(DeleteBehavior.Restrict);
builder.HasIndex(definition => new { definition.MonsterDefinitionId, definition.InstanceId });
}
/// <summary>
/// Applies the settings for the <see cref="CastleSiegeData"/> entity.
/// </summary>
/// <param name="builder">The builder.</param>
public static void Apply(this EntityTypeBuilder<CastleSiegeData> builder)
{
builder.HasOne<Guild>()
.WithMany()
.HasForeignKey(data => data.OwnerGuildId)
.OnDelete(DeleteBehavior.SetNull);
}
/// <summary>
/// Applies the settings for the <see cref="CastleSiegeNpcState"/> entity.
/// </summary>
/// <param name="builder">The builder.</param>
public static void Apply(this EntityTypeBuilder<CastleSiegeNpcState> builder)
{
builder.HasIndex(state => new { state.MonsterNumber, state.InstanceId }).IsUnique();
}
/// <summary>
/// Applies the settings for the <see cref="CastleSiegeGuildRegistration"/> entity.
/// </summary>
/// <param name="builder">The builder.</param>
public static void Apply(this EntityTypeBuilder<CastleSiegeGuildRegistration> builder)
{
builder.Property(registration => registration.GuildName).HasMaxLength(8).IsRequired();
builder.HasIndex(registration => registration.GuildId).IsUnique();
builder.HasOne<Guild>()
.WithMany()
.HasForeignKey(registration => registration.GuildId)
.OnDelete(DeleteBehavior.Cascade);
}
}

View File

@@ -1,9 +1,13 @@
using Microsoft.EntityFrameworkCore.Migrations;
// <copyright file="20260710205741_AddIsQuestItemFlag.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
#nullable disable
namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
{
using Microsoft.EntityFrameworkCore.Migrations;
/// <inheritdoc />
public partial class AddIsQuestItemFlag : Migration
{

View File

@@ -1,10 +1,14 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
// <copyright file="20260712014203_AddBuff.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
#nullable disable
namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
{
using System;
using Microsoft.EntityFrameworkCore.Migrations;
/// <inheritdoc />
public partial class AddBuff : Migration
{
@@ -20,7 +24,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
MagicEffectDefinitionId = table.Column<Guid>(type: "uuid", nullable: true),
MonsterDefinitionId = table.Column<Guid>(type: "uuid", nullable: true),
MinimumLevel = table.Column<int>(type: "integer", nullable: true),
MaximumLevel = table.Column<int>(type: "integer", nullable: true)
MaximumLevel = table.Column<int>(type: "integer", nullable: true),
},
constraints: table =>
{

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,453 @@
// <copyright file="20260730194321_AddCastleSiege.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
#nullable disable
namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
{
using System;
using Microsoft.EntityFrameworkCore.Migrations;
/// <inheritdoc />
public partial class AddCastleSiege : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
name: "CastleSiegeConfigurationId",
schema: "config",
table: "GameConfiguration",
type: "uuid",
nullable: true);
migrationBuilder.CreateTable(
name: "CastleSiegeData",
schema: "data",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
OwnerGuildId = table.Column<Guid>(type: "uuid", nullable: true),
IsOccupied = table.Column<bool>(type: "boolean", nullable: false),
TaxChaos = table.Column<byte>(type: "smallint", nullable: false),
TaxStore = table.Column<byte>(type: "smallint", nullable: false),
TaxHunt = table.Column<int>(type: "integer", nullable: false),
IsHuntZoneEnabled = table.Column<bool>(type: "boolean", nullable: false),
TributeMoney = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeData", x => x.Id);
});
migrationBuilder.CreateTable(
name: "CastleSiegeNpcState",
schema: "data",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CastleSiegeDataId = table.Column<Guid>(type: "uuid", nullable: true),
MonsterNumber = table.Column<short>(type: "smallint", nullable: false),
InstanceId = table.Column<byte>(type: "smallint", nullable: false),
DefenseLevel = table.Column<byte>(type: "smallint", nullable: false),
RegenLevel = table.Column<byte>(type: "smallint", nullable: false),
LifeLevel = table.Column<byte>(type: "smallint", nullable: false),
CurrentHp = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeNpcState", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeNpcState_CastleSiegeData_CastleSiegeDataId",
column: x => x.CastleSiegeDataId,
principalSchema: "data",
principalTable: "CastleSiegeData",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "CastleSiegeConfiguration",
schema: "config",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CastleSiegeMapDefinitionId = table.Column<Guid>(type: "uuid", nullable: true),
LandOfTrialsMapDefinitionId = table.Column<Guid>(type: "uuid", nullable: true),
RewardItemDefinitionId = table.Column<Guid>(type: "uuid", nullable: true),
DefenseRespawnAreaId = table.Column<Guid>(type: "uuid", nullable: true),
AttackRespawnAreaId = table.Column<Guid>(type: "uuid", nullable: true),
Enabled = table.Column<bool>(type: "boolean", nullable: false),
CrownHoldTimeSeconds = table.Column<int>(type: "integer", nullable: false),
RegisterMinLevel = table.Column<int>(type: "integer", nullable: false),
RegisterMinMembers = table.Column<int>(type: "integer", nullable: false),
ParticipantRewardMinSeconds = table.Column<int>(type: "integer", nullable: false),
MaxAttackingGuilds = table.Column<int>(type: "integer", nullable: false),
GuildScoreCastleSiege = table.Column<int>(type: "integer", nullable: false),
GuildScoreCastleSiegeMembers = table.Column<int>(type: "integer", nullable: false),
GateBuyPrice = table.Column<int>(type: "integer", nullable: false),
StatueBuyPrice = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeConfiguration", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_CastleSiegeMapDe~",
column: x => x.CastleSiegeMapDefinitionId,
principalSchema: "config",
principalTable: "GameMapDefinition",
principalColumn: "Id");
table.ForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_LandOfTrialsMapD~",
column: x => x.LandOfTrialsMapDefinitionId,
principalSchema: "config",
principalTable: "GameMapDefinition",
principalColumn: "Id");
table.ForeignKey(
name: "FK_CastleSiegeConfiguration_ItemDefinition_RewardItemDefinitio~",
column: x => x.RewardItemDefinitionId,
principalSchema: "config",
principalTable: "ItemDefinition",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "CastleSiegeNpcDefinition",
schema: "config",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
MonsterDefinitionId = table.Column<Guid>(type: "uuid", nullable: true),
CastleSiegeConfigurationId = table.Column<Guid>(type: "uuid", nullable: true),
InstanceId = table.Column<byte>(type: "smallint", nullable: false),
IsPersistedToDatabase = table.Column<bool>(type: "boolean", nullable: false),
DefaultSide = table.Column<byte>(type: "smallint", nullable: false),
SpawnX = table.Column<byte>(type: "smallint", nullable: false),
SpawnY = table.Column<byte>(type: "smallint", nullable: false),
Direction = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeNpcDefinition", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeNpcDefinition_CastleSiegeConfiguration_CastleSie~",
column: x => x.CastleSiegeConfigurationId,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CastleSiegeNpcDefinition_MonsterDefinition_MonsterDefinitio~",
column: x => x.MonsterDefinitionId,
principalSchema: "config",
principalTable: "MonsterDefinition",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "CastleSiegeStateScheduleEntry",
schema: "config",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CastleSiegeConfigurationId = table.Column<Guid>(type: "uuid", nullable: true),
State = table.Column<byte>(type: "smallint", nullable: false),
DayOfWeek = table.Column<int>(type: "integer", nullable: false),
Hour = table.Column<byte>(type: "smallint", nullable: false),
Minute = table.Column<byte>(type: "smallint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeStateScheduleEntry", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeStateScheduleEntry_CastleSiegeConfiguration_Cast~",
column: x => x.CastleSiegeConfigurationId,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "CastleSiegeUpgradeDefinition",
schema: "config",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CastleSiegeConfigurationId = table.Column<Guid>(type: "uuid", nullable: true),
CastleSiegeConfigurationId1 = table.Column<Guid>(type: "uuid", nullable: true),
CastleSiegeConfigurationId2 = table.Column<Guid>(type: "uuid", nullable: true),
CastleSiegeConfigurationId3 = table.Column<Guid>(type: "uuid", nullable: true),
CastleSiegeConfigurationId4 = table.Column<Guid>(type: "uuid", nullable: true),
Level = table.Column<byte>(type: "smallint", nullable: false),
RequiredJewelOfGuardianCount = table.Column<int>(type: "integer", nullable: false),
RequiredZen = table.Column<int>(type: "integer", nullable: false),
Value = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeUpgradeDefinition", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Castl~",
column: x => x.CastleSiegeConfigurationId,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~1",
column: x => x.CastleSiegeConfigurationId1,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~2",
column: x => x.CastleSiegeConfigurationId2,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~3",
column: x => x.CastleSiegeConfigurationId3,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~4",
column: x => x.CastleSiegeConfigurationId4,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "CastleSiegeZoneDefinition",
schema: "config",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
CastleSiegeConfigurationId = table.Column<Guid>(type: "uuid", nullable: true),
CastleSiegeConfigurationId1 = table.Column<Guid>(type: "uuid", nullable: true),
X1 = table.Column<byte>(type: "smallint", nullable: false),
Y1 = table.Column<byte>(type: "smallint", nullable: false),
X2 = table.Column<byte>(type: "smallint", nullable: false),
Y2 = table.Column<byte>(type: "smallint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeZoneDefinition", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeZoneDefinition_CastleSiegeConfiguration_CastleSi~",
column: x => x.CastleSiegeConfigurationId,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_CastleSiegeZoneDefinition_CastleSiegeConfiguration_CastleS~1",
column: x => x.CastleSiegeConfigurationId1,
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_GameConfiguration_CastleSiegeConfigurationId",
schema: "config",
table: "GameConfiguration",
column: "CastleSiegeConfigurationId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeConfiguration_AttackRespawnAreaId",
schema: "config",
table: "CastleSiegeConfiguration",
column: "AttackRespawnAreaId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeConfiguration_CastleSiegeMapDefinitionId",
schema: "config",
table: "CastleSiegeConfiguration",
column: "CastleSiegeMapDefinitionId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeConfiguration_DefenseRespawnAreaId",
schema: "config",
table: "CastleSiegeConfiguration",
column: "DefenseRespawnAreaId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeConfiguration_LandOfTrialsMapDefinitionId",
schema: "config",
table: "CastleSiegeConfiguration",
column: "LandOfTrialsMapDefinitionId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeConfiguration_RewardItemDefinitionId",
schema: "config",
table: "CastleSiegeConfiguration",
column: "RewardItemDefinitionId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeNpcDefinition_CastleSiegeConfigurationId",
schema: "config",
table: "CastleSiegeNpcDefinition",
column: "CastleSiegeConfigurationId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeNpcDefinition_MonsterDefinitionId",
schema: "config",
table: "CastleSiegeNpcDefinition",
column: "MonsterDefinitionId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeNpcState_CastleSiegeDataId",
schema: "data",
table: "CastleSiegeNpcState",
column: "CastleSiegeDataId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeStateScheduleEntry_CastleSiegeConfigurationId",
schema: "config",
table: "CastleSiegeStateScheduleEntry",
column: "CastleSiegeConfigurationId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeUpgradeDefinition_CastleSiegeConfigurationId",
schema: "config",
table: "CastleSiegeUpgradeDefinition",
column: "CastleSiegeConfigurationId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeUpgradeDefinition_CastleSiegeConfigurationId1",
schema: "config",
table: "CastleSiegeUpgradeDefinition",
column: "CastleSiegeConfigurationId1");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeUpgradeDefinition_CastleSiegeConfigurationId2",
schema: "config",
table: "CastleSiegeUpgradeDefinition",
column: "CastleSiegeConfigurationId2");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeUpgradeDefinition_CastleSiegeConfigurationId3",
schema: "config",
table: "CastleSiegeUpgradeDefinition",
column: "CastleSiegeConfigurationId3");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeUpgradeDefinition_CastleSiegeConfigurationId4",
schema: "config",
table: "CastleSiegeUpgradeDefinition",
column: "CastleSiegeConfigurationId4");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeZoneDefinition_CastleSiegeConfigurationId",
schema: "config",
table: "CastleSiegeZoneDefinition",
column: "CastleSiegeConfigurationId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeZoneDefinition_CastleSiegeConfigurationId1",
schema: "config",
table: "CastleSiegeZoneDefinition",
column: "CastleSiegeConfigurationId1");
migrationBuilder.AddForeignKey(
name: "FK_GameConfiguration_CastleSiegeConfiguration_CastleSiegeConfi~",
schema: "config",
table: "GameConfiguration",
column: "CastleSiegeConfigurationId",
principalSchema: "config",
principalTable: "CastleSiegeConfiguration",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_CastleSiegeZoneDefinition_AttackRe~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "AttackRespawnAreaId",
principalSchema: "config",
principalTable: "CastleSiegeZoneDefinition",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_CastleSiegeZoneDefinition_DefenseR~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "DefenseRespawnAreaId",
principalSchema: "config",
principalTable: "CastleSiegeZoneDefinition",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_GameConfiguration_CastleSiegeConfiguration_CastleSiegeConfi~",
schema: "config",
table: "GameConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_CastleSiegeZoneDefinition_AttackRe~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_CastleSiegeZoneDefinition_DefenseR~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropTable(
name: "CastleSiegeNpcDefinition",
schema: "config");
migrationBuilder.DropTable(
name: "CastleSiegeNpcState",
schema: "data");
migrationBuilder.DropTable(
name: "CastleSiegeStateScheduleEntry",
schema: "config");
migrationBuilder.DropTable(
name: "CastleSiegeUpgradeDefinition",
schema: "config");
migrationBuilder.DropTable(
name: "CastleSiegeData",
schema: "data");
migrationBuilder.DropTable(
name: "CastleSiegeZoneDefinition",
schema: "config");
migrationBuilder.DropTable(
name: "CastleSiegeConfiguration",
schema: "config");
migrationBuilder.DropIndex(
name: "IX_GameConfiguration_CastleSiegeConfigurationId",
schema: "config",
table: "GameConfiguration");
migrationBuilder.DropColumn(
name: "CastleSiegeConfigurationId",
schema: "config",
table: "GameConfiguration");
}
}
}

View File

@@ -0,0 +1,343 @@
// <copyright file="20260801162427_ConfigureCastleSiegePersistence.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
#nullable disable
namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
{
using System;
using Microsoft.EntityFrameworkCore.Migrations;
/// <inheritdoc />
public partial class ConfigureCastleSiegePersistence : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_CastleSiegeMapDe~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_LandOfTrialsMapD~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_ItemDefinition_RewardItemDefinitio~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeNpcDefinition_MonsterDefinition_MonsterDefinitio~",
schema: "config",
table: "CastleSiegeNpcDefinition");
migrationBuilder.DropIndex(
name: "IX_CastleSiegeNpcDefinition_MonsterDefinitionId",
schema: "config",
table: "CastleSiegeNpcDefinition");
migrationBuilder.Sql(
"""
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM config."CastleSiegeNpcDefinition" WHERE "MonsterDefinitionId" IS NULL) THEN
RAISE EXCEPTION 'CastleSiegeNpcDefinition contains rows without a MonsterDefinitionId. Repair or remove these rows before applying this migration.';
END IF;
END
$$;
""");
migrationBuilder.AlterColumn<Guid>(
name: "MonsterDefinitionId",
schema: "config",
table: "CastleSiegeNpcDefinition",
type: "uuid",
nullable: false,
oldClrType: typeof(Guid),
oldType: "uuid",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "RegisterMinMembers",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
defaultValue: 20,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.AlterColumn<int>(
name: "RegisterMinLevel",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
defaultValue: 200,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.AlterColumn<int>(
name: "MaxAttackingGuilds",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
defaultValue: 3,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.AlterColumn<int>(
name: "CrownHoldTimeSeconds",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
defaultValue: 30,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.CreateTable(
name: "CastleSiegeGuildRegistration",
schema: "data",
columns: table => new
{
Id = table.Column<Guid>(type: "uuid", nullable: false),
GuildId = table.Column<Guid>(type: "uuid", nullable: false),
GuildName = table.Column<string>(type: "character varying(8)", maxLength: 8, nullable: false),
Marks = table.Column<int>(type: "integer", nullable: false),
RegistrationOrder = table.Column<int>(type: "integer", nullable: false),
},
constraints: table =>
{
table.PrimaryKey("PK_CastleSiegeGuildRegistration", x => x.Id);
table.ForeignKey(
name: "FK_CastleSiegeGuildRegistration_Guild_GuildId",
column: x => x.GuildId,
principalSchema: "guild",
principalTable: "Guild",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeNpcState_MonsterNumber_InstanceId",
schema: "data",
table: "CastleSiegeNpcState",
columns: new[] { "MonsterNumber", "InstanceId" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeNpcDefinition_MonsterDefinitionId_InstanceId",
schema: "config",
table: "CastleSiegeNpcDefinition",
columns: new[] { "MonsterDefinitionId", "InstanceId" });
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeData_OwnerGuildId",
schema: "data",
table: "CastleSiegeData",
column: "OwnerGuildId");
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeGuildRegistration_GuildId",
schema: "data",
table: "CastleSiegeGuildRegistration",
column: "GuildId",
unique: true);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_CastleSiegeMapDe~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "CastleSiegeMapDefinitionId",
principalSchema: "config",
principalTable: "GameMapDefinition",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_LandOfTrialsMapD~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "LandOfTrialsMapDefinitionId",
principalSchema: "config",
principalTable: "GameMapDefinition",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_ItemDefinition_RewardItemDefinitio~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "RewardItemDefinitionId",
principalSchema: "config",
principalTable: "ItemDefinition",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeData_Guild_OwnerGuildId",
schema: "data",
table: "CastleSiegeData",
column: "OwnerGuildId",
principalSchema: "guild",
principalTable: "Guild",
principalColumn: "Id",
onDelete: ReferentialAction.SetNull);
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeNpcDefinition_MonsterDefinition_MonsterDefinitio~",
schema: "config",
table: "CastleSiegeNpcDefinition",
column: "MonsterDefinitionId",
principalSchema: "config",
principalTable: "MonsterDefinition",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_CastleSiegeMapDe~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_LandOfTrialsMapD~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeConfiguration_ItemDefinition_RewardItemDefinitio~",
schema: "config",
table: "CastleSiegeConfiguration");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeData_Guild_OwnerGuildId",
schema: "data",
table: "CastleSiegeData");
migrationBuilder.DropForeignKey(
name: "FK_CastleSiegeNpcDefinition_MonsterDefinition_MonsterDefinitio~",
schema: "config",
table: "CastleSiegeNpcDefinition");
migrationBuilder.DropTable(
name: "CastleSiegeGuildRegistration",
schema: "data");
migrationBuilder.DropIndex(
name: "IX_CastleSiegeNpcState_MonsterNumber_InstanceId",
schema: "data",
table: "CastleSiegeNpcState");
migrationBuilder.DropIndex(
name: "IX_CastleSiegeNpcDefinition_MonsterDefinitionId_InstanceId",
schema: "config",
table: "CastleSiegeNpcDefinition");
migrationBuilder.DropIndex(
name: "IX_CastleSiegeData_OwnerGuildId",
schema: "data",
table: "CastleSiegeData");
migrationBuilder.AlterColumn<Guid>(
name: "MonsterDefinitionId",
schema: "config",
table: "CastleSiegeNpcDefinition",
type: "uuid",
nullable: true,
oldClrType: typeof(Guid),
oldType: "uuid");
migrationBuilder.AlterColumn<int>(
name: "RegisterMinMembers",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
oldClrType: typeof(int),
oldType: "integer",
oldDefaultValue: 20);
migrationBuilder.AlterColumn<int>(
name: "RegisterMinLevel",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
oldClrType: typeof(int),
oldType: "integer",
oldDefaultValue: 200);
migrationBuilder.AlterColumn<int>(
name: "MaxAttackingGuilds",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
oldClrType: typeof(int),
oldType: "integer",
oldDefaultValue: 3);
migrationBuilder.AlterColumn<int>(
name: "CrownHoldTimeSeconds",
schema: "config",
table: "CastleSiegeConfiguration",
type: "integer",
nullable: false,
oldClrType: typeof(int),
oldType: "integer",
oldDefaultValue: 30);
migrationBuilder.CreateIndex(
name: "IX_CastleSiegeNpcDefinition_MonsterDefinitionId",
schema: "config",
table: "CastleSiegeNpcDefinition",
column: "MonsterDefinitionId");
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_CastleSiegeMapDe~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "CastleSiegeMapDefinitionId",
principalSchema: "config",
principalTable: "GameMapDefinition",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_GameMapDefinition_LandOfTrialsMapD~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "LandOfTrialsMapDefinitionId",
principalSchema: "config",
principalTable: "GameMapDefinition",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeConfiguration_ItemDefinition_RewardItemDefinitio~",
schema: "config",
table: "CastleSiegeConfiguration",
column: "RewardItemDefinitionId",
principalSchema: "config",
principalTable: "ItemDefinition",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_CastleSiegeNpcDefinition_MonsterDefinition_MonsterDefinitio~",
schema: "config",
table: "CastleSiegeNpcDefinition",
column: "MonsterDefinitionId",
principalSchema: "config",
principalTable: "MonsterDefinition",
principalColumn: "Id");
}
}
}

View File

@@ -378,6 +378,329 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
b.ToTable("Buff", "config");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("AttackRespawnAreaId")
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeMapDefinitionId")
.HasColumnType("uuid");
b.Property<int>("CrownHoldTimeSeconds")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(30);
b.Property<Guid?>("DefenseRespawnAreaId")
.HasColumnType("uuid");
b.Property<bool>("Enabled")
.HasColumnType("boolean");
b.Property<int>("GateBuyPrice")
.HasColumnType("integer");
b.Property<int>("GuildScoreCastleSiege")
.HasColumnType("integer");
b.Property<int>("GuildScoreCastleSiegeMembers")
.HasColumnType("integer");
b.Property<Guid?>("LandOfTrialsMapDefinitionId")
.HasColumnType("uuid");
b.Property<int>("MaxAttackingGuilds")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(3);
b.Property<int>("ParticipantRewardMinSeconds")
.HasColumnType("integer");
b.Property<int>("RegisterMinLevel")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(200);
b.Property<int>("RegisterMinMembers")
.ValueGeneratedOnAdd()
.HasColumnType("integer")
.HasDefaultValue(20);
b.Property<Guid?>("RewardItemDefinitionId")
.HasColumnType("uuid");
b.Property<int>("StatueBuyPrice")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("AttackRespawnAreaId")
.IsUnique();
b.HasIndex("CastleSiegeMapDefinitionId");
b.HasIndex("DefenseRespawnAreaId")
.IsUnique();
b.HasIndex("LandOfTrialsMapDefinitionId");
b.HasIndex("RewardItemDefinitionId");
b.ToTable("CastleSiegeConfiguration", "config");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeData", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<bool>("IsHuntZoneEnabled")
.HasColumnType("boolean");
b.Property<bool>("IsOccupied")
.HasColumnType("boolean");
b.Property<Guid?>("OwnerGuildId")
.HasColumnType("uuid");
b.Property<byte>("TaxChaos")
.HasColumnType("smallint");
b.Property<int>("TaxHunt")
.HasColumnType("integer");
b.Property<byte>("TaxStore")
.HasColumnType("smallint");
b.Property<long>("TributeMoney")
.HasColumnType("bigint");
b.HasKey("Id");
b.HasIndex("OwnerGuildId");
b.ToTable("CastleSiegeData", "data");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeGuildRegistration", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid>("GuildId")
.HasColumnType("uuid");
b.Property<string>("GuildName")
.IsRequired()
.HasMaxLength(8)
.HasColumnType("character varying(8)");
b.Property<int>("Marks")
.HasColumnType("integer");
b.Property<int>("RegistrationOrder")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("CastleSiegeGuildRegistration", "data");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeNpcDefinition", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId")
.HasColumnType("uuid");
b.Property<byte>("DefaultSide")
.HasColumnType("smallint");
b.Property<int>("Direction")
.HasColumnType("integer");
b.Property<byte>("InstanceId")
.HasColumnType("smallint");
b.Property<bool>("IsPersistedToDatabase")
.HasColumnType("boolean");
b.Property<Guid>("MonsterDefinitionId")
.HasColumnType("uuid");
b.Property<byte>("SpawnX")
.HasColumnType("smallint");
b.Property<byte>("SpawnY")
.HasColumnType("smallint");
b.HasKey("Id");
b.HasIndex("CastleSiegeConfigurationId");
b.HasIndex("MonsterDefinitionId", "InstanceId");
b.ToTable("CastleSiegeNpcDefinition", "config");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeNpcState", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeDataId")
.HasColumnType("uuid");
b.Property<int>("CurrentHp")
.HasColumnType("integer");
b.Property<byte>("DefenseLevel")
.HasColumnType("smallint");
b.Property<byte>("InstanceId")
.HasColumnType("smallint");
b.Property<byte>("LifeLevel")
.HasColumnType("smallint");
b.Property<short>("MonsterNumber")
.HasColumnType("smallint");
b.Property<byte>("RegenLevel")
.HasColumnType("smallint");
b.HasKey("Id");
b.HasIndex("CastleSiegeDataId");
b.HasIndex("MonsterNumber", "InstanceId")
.IsUnique();
b.ToTable("CastleSiegeNpcState", "data");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeStateScheduleEntry", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId")
.HasColumnType("uuid");
b.Property<int>("DayOfWeek")
.HasColumnType("integer");
b.Property<byte>("Hour")
.HasColumnType("smallint");
b.Property<byte>("Minute")
.HasColumnType("smallint");
b.Property<byte>("State")
.HasColumnType("smallint");
b.HasKey("Id");
b.HasIndex("CastleSiegeConfigurationId");
b.ToTable("CastleSiegeStateScheduleEntry", "config");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeUpgradeDefinition", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId")
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId1")
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId2")
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId3")
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId4")
.HasColumnType("uuid");
b.Property<byte>("Level")
.HasColumnType("smallint");
b.Property<int>("RequiredJewelOfGuardianCount")
.HasColumnType("integer");
b.Property<int>("RequiredZen")
.HasColumnType("integer");
b.Property<int>("Value")
.HasColumnType("integer");
b.HasKey("Id");
b.HasIndex("CastleSiegeConfigurationId");
b.HasIndex("CastleSiegeConfigurationId1");
b.HasIndex("CastleSiegeConfigurationId2");
b.HasIndex("CastleSiegeConfigurationId3");
b.HasIndex("CastleSiegeConfigurationId4");
b.ToTable("CastleSiegeUpgradeDefinition", "config");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeZoneDefinition", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId")
.HasColumnType("uuid");
b.Property<Guid?>("CastleSiegeConfigurationId1")
.HasColumnType("uuid");
b.Property<byte>("X1")
.HasColumnType("smallint");
b.Property<byte>("X2")
.HasColumnType("smallint");
b.Property<byte>("Y1")
.HasColumnType("smallint");
b.Property<byte>("Y2")
.HasColumnType("smallint");
b.HasKey("Id");
b.HasIndex("CastleSiegeConfigurationId");
b.HasIndex("CastleSiegeConfigurationId1");
b.ToTable("CastleSiegeZoneDefinition", "config");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", b =>
{
b.Property<Guid>("Id")
@@ -1054,6 +1377,9 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
b.Property<bool>("AreaSkillHitsPlayer")
.HasColumnType("boolean");
b.Property<Guid?>("CastleSiegeConfigurationId")
.HasColumnType("uuid");
b.Property<string>("CharacterNameRegex")
.HasColumnType("text");
@@ -1145,6 +1471,9 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
b.HasKey("Id");
b.HasIndex("CastleSiegeConfigurationId")
.IsUnique();
b.HasIndex("DuelConfigurationId")
.IsUnique();
@@ -3638,6 +3967,139 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
b.Navigation("RawMagicEffectDefinition");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeZoneDefinition", "RawAttackRespawnArea")
.WithOne()
.HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", "AttackRespawnAreaId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawCastleSiegeMapDefinition")
.WithMany()
.HasForeignKey("CastleSiegeMapDefinitionId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeZoneDefinition", "RawDefenseRespawnArea")
.WithOne()
.HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", "DefenseRespawnAreaId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.GameMapDefinition", "RawLandOfTrialsMapDefinition")
.WithMany()
.HasForeignKey("LandOfTrialsMapDefinitionId")
.OnDelete(DeleteBehavior.Restrict);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.ItemDefinition", "RawRewardItemDefinition")
.WithMany()
.HasForeignKey("RewardItemDefinitionId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("RawAttackRespawnArea");
b.Navigation("RawCastleSiegeMapDefinition");
b.Navigation("RawDefenseRespawnArea");
b.Navigation("RawLandOfTrialsMapDefinition");
b.Navigation("RawRewardItemDefinition");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeData", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", null)
.WithMany()
.HasForeignKey("OwnerGuildId")
.OnDelete(DeleteBehavior.SetNull);
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeGuildRegistration", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Guild", null)
.WithMany()
.HasForeignKey("GuildId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeNpcDefinition", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawNpcDefinitions")
.HasForeignKey("CastleSiegeConfigurationId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.MonsterDefinition", "RawMonsterDefinition")
.WithMany()
.HasForeignKey("MonsterDefinitionId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("RawMonsterDefinition");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeNpcState", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeData", null)
.WithMany("RawNpcStates")
.HasForeignKey("CastleSiegeDataId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeStateScheduleEntry", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawStateSchedule")
.HasForeignKey("CastleSiegeConfigurationId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeUpgradeDefinition", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawGateDefenseUpgrades")
.HasForeignKey("CastleSiegeConfigurationId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawGateLifeUpgrades")
.HasForeignKey("CastleSiegeConfigurationId1")
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~1");
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawStatueDefenseUpgrades")
.HasForeignKey("CastleSiegeConfigurationId2")
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~2");
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawStatueLifeUpgrades")
.HasForeignKey("CastleSiegeConfigurationId3")
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~3");
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawStatueRegenUpgrades")
.HasForeignKey("CastleSiegeConfigurationId4")
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("FK_CastleSiegeUpgradeDefinition_CastleSiegeConfiguration_Cast~4");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeZoneDefinition", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawAttackMachineZones")
.HasForeignKey("CastleSiegeConfigurationId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", null)
.WithMany("RawDefenseMachineZones")
.HasForeignKey("CastleSiegeConfigurationId1")
.OnDelete(DeleteBehavior.Cascade)
.HasConstraintName("FK_CastleSiegeZoneDefinition_CastleSiegeConfiguration_CastleS~1");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.Account", null)
@@ -3887,11 +4349,18 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", b =>
{
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", "RawCastleSiegeConfiguration")
.WithOne()
.HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", "CastleSiegeConfigurationId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("MUnique.OpenMU.Persistence.EntityFramework.Model.DuelConfiguration", "RawDuelConfiguration")
.WithOne()
.HasForeignKey("MUnique.OpenMU.Persistence.EntityFramework.Model.GameConfiguration", "DuelConfigurationId")
.OnDelete(DeleteBehavior.Cascade);
b.Navigation("RawCastleSiegeConfiguration");
b.Navigation("RawDuelConfiguration");
});
@@ -5023,6 +5492,32 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
b.Navigation("RawEquippedItems");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeConfiguration", b =>
{
b.Navigation("RawAttackMachineZones");
b.Navigation("RawDefenseMachineZones");
b.Navigation("RawGateDefenseUpgrades");
b.Navigation("RawGateLifeUpgrades");
b.Navigation("RawNpcDefinitions");
b.Navigation("RawStateSchedule");
b.Navigation("RawStatueDefenseUpgrades");
b.Navigation("RawStatueLifeUpgrades");
b.Navigation("RawStatueRegenUpgrades");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.CastleSiegeData", b =>
{
b.Navigation("RawNpcStates");
});
modelBuilder.Entity("MUnique.OpenMU.Persistence.EntityFramework.Model.Character", b =>
{
b.Navigation("JoinedDropItemGroups");

View File

@@ -0,0 +1,276 @@
// <copyright file="CastleSiegeConfiguration.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration"/>.
/// </summary>
[Table(nameof(CastleSiegeConfiguration), Schema = SchemaNames.Configuration)]
internal partial class CastleSiegeConfiguration : MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration, IIdentifiable
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets the raw collection of <see cref="StateSchedule" />.
/// </summary>
public ICollection<CastleSiegeStateScheduleEntry> RawStateSchedule { get; } = new EntityFramework.List<CastleSiegeStateScheduleEntry>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry> StateSchedule => base.StateSchedule ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry, CastleSiegeStateScheduleEntry>(this.RawStateSchedule);
/// <summary>
/// Gets the raw collection of <see cref="NpcDefinitions" />.
/// </summary>
public ICollection<CastleSiegeNpcDefinition> RawNpcDefinitions { get; } = new EntityFramework.List<CastleSiegeNpcDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition> NpcDefinitions => base.NpcDefinitions ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition, CastleSiegeNpcDefinition>(this.RawNpcDefinitions);
/// <summary>
/// Gets the raw collection of <see cref="GateDefenseUpgrades" />.
/// </summary>
public ICollection<CastleSiegeUpgradeDefinition> RawGateDefenseUpgrades { get; } = new EntityFramework.List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> GateDefenseUpgrades => base.GateDefenseUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawGateDefenseUpgrades);
/// <summary>
/// Gets the raw collection of <see cref="GateLifeUpgrades" />.
/// </summary>
public ICollection<CastleSiegeUpgradeDefinition> RawGateLifeUpgrades { get; } = new EntityFramework.List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> GateLifeUpgrades => base.GateLifeUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawGateLifeUpgrades);
/// <summary>
/// Gets the raw collection of <see cref="StatueDefenseUpgrades" />.
/// </summary>
public ICollection<CastleSiegeUpgradeDefinition> RawStatueDefenseUpgrades { get; } = new EntityFramework.List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> StatueDefenseUpgrades => base.StatueDefenseUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawStatueDefenseUpgrades);
/// <summary>
/// Gets the raw collection of <see cref="StatueLifeUpgrades" />.
/// </summary>
public ICollection<CastleSiegeUpgradeDefinition> RawStatueLifeUpgrades { get; } = new EntityFramework.List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> StatueLifeUpgrades => base.StatueLifeUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawStatueLifeUpgrades);
/// <summary>
/// Gets the raw collection of <see cref="StatueRegenUpgrades" />.
/// </summary>
public ICollection<CastleSiegeUpgradeDefinition> RawStatueRegenUpgrades { get; } = new EntityFramework.List<CastleSiegeUpgradeDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition> StatueRegenUpgrades => base.StatueRegenUpgrades ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, CastleSiegeUpgradeDefinition>(this.RawStatueRegenUpgrades);
/// <summary>
/// Gets the raw collection of <see cref="AttackMachineZones" />.
/// </summary>
public ICollection<CastleSiegeZoneDefinition> RawAttackMachineZones { get; } = new EntityFramework.List<CastleSiegeZoneDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition> AttackMachineZones => base.AttackMachineZones ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition, CastleSiegeZoneDefinition>(this.RawAttackMachineZones);
/// <summary>
/// Gets the raw collection of <see cref="DefenseMachineZones" />.
/// </summary>
public ICollection<CastleSiegeZoneDefinition> RawDefenseMachineZones { get; } = new EntityFramework.List<CastleSiegeZoneDefinition>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition> DefenseMachineZones => base.DefenseMachineZones ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition, CastleSiegeZoneDefinition>(this.RawDefenseMachineZones);
/// <summary>
/// Gets or sets the identifier of <see cref="CastleSiegeMapDefinition"/>.
/// </summary>
public Guid? CastleSiegeMapDefinitionId { get; set; }
/// <summary>
/// Gets the raw object of <see cref="CastleSiegeMapDefinition" />.
/// </summary>
[ForeignKey(nameof(CastleSiegeMapDefinitionId))]
public GameMapDefinition RawCastleSiegeMapDefinition
{
get => base.CastleSiegeMapDefinition as GameMapDefinition;
set => base.CastleSiegeMapDefinition = value;
}
/// <inheritdoc/>
[NotMapped]
public override MUnique.OpenMU.DataModel.Configuration.GameMapDefinition CastleSiegeMapDefinition
{
get => base.CastleSiegeMapDefinition;set
{
base.CastleSiegeMapDefinition = value;
this.CastleSiegeMapDefinitionId = this.RawCastleSiegeMapDefinition?.Id;
}
}
/// <summary>
/// Gets or sets the identifier of <see cref="LandOfTrialsMapDefinition"/>.
/// </summary>
public Guid? LandOfTrialsMapDefinitionId { get; set; }
/// <summary>
/// Gets the raw object of <see cref="LandOfTrialsMapDefinition" />.
/// </summary>
[ForeignKey(nameof(LandOfTrialsMapDefinitionId))]
public GameMapDefinition RawLandOfTrialsMapDefinition
{
get => base.LandOfTrialsMapDefinition as GameMapDefinition;
set => base.LandOfTrialsMapDefinition = value;
}
/// <inheritdoc/>
[NotMapped]
public override MUnique.OpenMU.DataModel.Configuration.GameMapDefinition LandOfTrialsMapDefinition
{
get => base.LandOfTrialsMapDefinition;set
{
base.LandOfTrialsMapDefinition = value;
this.LandOfTrialsMapDefinitionId = this.RawLandOfTrialsMapDefinition?.Id;
}
}
/// <summary>
/// Gets or sets the identifier of <see cref="RewardItemDefinition"/>.
/// </summary>
public Guid? RewardItemDefinitionId { get; set; }
/// <summary>
/// Gets the raw object of <see cref="RewardItemDefinition" />.
/// </summary>
[ForeignKey(nameof(RewardItemDefinitionId))]
public ItemDefinition RawRewardItemDefinition
{
get => base.RewardItemDefinition as ItemDefinition;
set => base.RewardItemDefinition = value;
}
/// <inheritdoc/>
[NotMapped]
public override MUnique.OpenMU.DataModel.Configuration.Items.ItemDefinition RewardItemDefinition
{
get => base.RewardItemDefinition;set
{
base.RewardItemDefinition = value;
this.RewardItemDefinitionId = this.RawRewardItemDefinition?.Id;
}
}
/// <summary>
/// Gets or sets the identifier of <see cref="DefenseRespawnArea"/>.
/// </summary>
public Guid? DefenseRespawnAreaId { get; set; }
/// <summary>
/// Gets the raw object of <see cref="DefenseRespawnArea" />.
/// </summary>
[ForeignKey(nameof(DefenseRespawnAreaId))]
public CastleSiegeZoneDefinition RawDefenseRespawnArea
{
get => base.DefenseRespawnArea as CastleSiegeZoneDefinition;
set => base.DefenseRespawnArea = value;
}
/// <inheritdoc/>
[NotMapped]
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition DefenseRespawnArea
{
get => base.DefenseRespawnArea;set
{
base.DefenseRespawnArea = value;
this.DefenseRespawnAreaId = this.RawDefenseRespawnArea?.Id;
}
}
/// <summary>
/// Gets or sets the identifier of <see cref="AttackRespawnArea"/>.
/// </summary>
public Guid? AttackRespawnAreaId { get; set; }
/// <summary>
/// Gets the raw object of <see cref="AttackRespawnArea" />.
/// </summary>
[ForeignKey(nameof(AttackRespawnAreaId))]
public CastleSiegeZoneDefinition RawAttackRespawnArea
{
get => base.AttackRespawnArea as CastleSiegeZoneDefinition;
set => base.AttackRespawnArea = value;
}
/// <inheritdoc/>
[NotMapped]
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition AttackRespawnArea
{
get => base.AttackRespawnArea;set
{
base.AttackRespawnArea = value;
this.AttackRespawnAreaId = this.RawAttackRespawnArea?.Id;
}
}
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeConfiguration();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeConfiguration other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,56 @@
// <copyright file="CastleSiegeData.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Entities.CastleSiegeData"/>.
/// </summary>
[Table(nameof(CastleSiegeData), Schema = SchemaNames.AccountData)]
internal partial class CastleSiegeData : MUnique.OpenMU.DataModel.Entities.CastleSiegeData, IIdentifiable
{
/// <summary>
/// Gets the raw collection of <see cref="NpcStates" />.
/// </summary>
public ICollection<CastleSiegeNpcState> RawNpcStates { get; } = new EntityFramework.List<CastleSiegeNpcState>();
/// <inheritdoc/>
[NotMapped]
public override ICollection<MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState> NpcStates => base.NpcStates ??= new CollectionAdapter<MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState, CastleSiegeNpcState>(this.RawNpcStates);
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,47 @@
// <copyright file="CastleSiegeGuildRegistration.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Entities.CastleSiegeGuildRegistration"/>.
/// </summary>
[Table(nameof(CastleSiegeGuildRegistration), Schema = SchemaNames.AccountData)]
internal partial class CastleSiegeGuildRegistration : MUnique.OpenMU.DataModel.Entities.CastleSiegeGuildRegistration, IIdentifiable
{
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,91 @@
// <copyright file="CastleSiegeNpcDefinition.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition"/>.
/// </summary>
[Table(nameof(CastleSiegeNpcDefinition), Schema = SchemaNames.Configuration)]
internal partial class CastleSiegeNpcDefinition : MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition, IIdentifiable
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <summary>
/// Gets or sets the identifier of <see cref="MonsterDefinition"/>.
/// </summary>
public Guid? MonsterDefinitionId { get; set; }
/// <summary>
/// Gets the raw object of <see cref="MonsterDefinition" />.
/// </summary>
[ForeignKey(nameof(MonsterDefinitionId))]
public MonsterDefinition RawMonsterDefinition
{
get => base.MonsterDefinition as MonsterDefinition;
set => base.MonsterDefinition = value;
}
/// <inheritdoc/>
[NotMapped]
public override MUnique.OpenMU.DataModel.Configuration.MonsterDefinition MonsterDefinition
{
get => base.MonsterDefinition;set
{
base.MonsterDefinition = value;
this.MonsterDefinitionId = this.RawMonsterDefinition?.Id;
}
}
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeNpcDefinition();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeNpcDefinition other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,47 @@
// <copyright file="CastleSiegeNpcState.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState"/>.
/// </summary>
[Table(nameof(CastleSiegeNpcState), Schema = SchemaNames.AccountData)]
internal partial class CastleSiegeNpcState : MUnique.OpenMU.DataModel.Entities.CastleSiegeNpcState, IIdentifiable
{
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,65 @@
// <copyright file="CastleSiegeStateScheduleEntry.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry"/>.
/// </summary>
[Table(nameof(CastleSiegeStateScheduleEntry), Schema = SchemaNames.Configuration)]
internal partial class CastleSiegeStateScheduleEntry : MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry, IIdentifiable
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeStateScheduleEntry();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeStateScheduleEntry other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,65 @@
// <copyright file="CastleSiegeUpgradeDefinition.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition"/>.
/// </summary>
[Table(nameof(CastleSiegeUpgradeDefinition), Schema = SchemaNames.Configuration)]
internal partial class CastleSiegeUpgradeDefinition : MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition, IIdentifiable
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeUpgradeDefinition();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeUpgradeDefinition other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,65 @@
// <copyright file="CastleSiegeZoneDefinition.Generated.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
//------------------------------------------------------------------------------
// <auto-generated>
// This source code was auto-generated by a roslyn code generator.
// </auto-generated>
//------------------------------------------------------------------------------
// ReSharper disable All
namespace MUnique.OpenMU.Persistence.EntityFramework.Model;
using System.ComponentModel.DataAnnotations.Schema;
using MUnique.OpenMU.Persistence;
/// <summary>
/// The Entity Framework Core implementation of <see cref="MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition"/>.
/// </summary>
[Table(nameof(CastleSiegeZoneDefinition), Schema = SchemaNames.Configuration)]
internal partial class CastleSiegeZoneDefinition : MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition, IIdentifiable
{
/// <summary>
/// Gets or sets the identifier of this instance.
/// </summary>
public Guid Id { get; set; }
/// <inheritdoc />
public override MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition Clone(MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
var clone = new CastleSiegeZoneDefinition();
clone.AssignValuesOf(this, gameConfiguration);
return clone;
}
/// <inheritdoc />
public override void AssignValuesOf(MUnique.OpenMU.DataModel.Configuration.CastleSiegeZoneDefinition other, MUnique.OpenMU.DataModel.Configuration.GameConfiguration gameConfiguration)
{
base.AssignValuesOf(other, gameConfiguration);
this.Id = other.GetId();
}
/// <inheritdoc/>
public override bool Equals(object obj)
{
var baseObject = obj as IIdentifiable;
if (baseObject != null)
{
return baseObject.Id == this.Id;
}
return base.Equals(obj);
}
/// <inheritdoc/>
public override int GetHashCode()
{
return this.Id.GetHashCode();
}
}

View File

@@ -0,0 +1,59 @@
// <copyright file="AddCastleSiegeDataUpdatePlugIn.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.Updates;
using System.Runtime.InteropServices;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.DataModel.Entities;
using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Events;
using MUnique.OpenMU.PlugIns;
/// <summary>
/// Adds the Castle Siege configuration and persistent state to an existing Season 6 database.
/// </summary>
[PlugIn]
[Display(Name = PlugInName, Description = PlugInDescription)]
[Guid("CD201E33-37C9-4C85-95CC-16042B28E974")]
public class AddCastleSiegeDataUpdatePlugIn : UpdatePlugInBase
{
/// <summary>
/// The plug-in name.
/// </summary>
internal const string PlugInName = "Add Castle Siege data";
/// <summary>
/// The plug-in description.
/// </summary>
internal const string PlugInDescription = "This update adds the Castle Siege configuration and persistent state.";
/// <inheritdoc />
public override string Name => PlugInName;
/// <inheritdoc />
public override string Description => PlugInDescription;
/// <inheritdoc />
public override UpdateVersion Version => UpdateVersion.AddCastleSiegeData;
/// <inheritdoc />
public override string DataInitializationKey => VersionSeasonSix.DataInitialization.Id;
/// <inheritdoc />
public override bool IsMandatory => true;
/// <inheritdoc />
public override DateTime CreatedAt => new(2026, 07, 28, 20, 0, 0, DateTimeKind.Utc);
/// <inheritdoc />
protected override async ValueTask ApplyAsync(IContext context, GameConfiguration gameConfiguration)
{
var initializer = new CastleSiegeInitializer(context, gameConfiguration);
var configuration = initializer.InitializeConfiguration();
if (!(await context.GetAsync<CastleSiegeData>().ConfigureAwait(false)).Any())
{
initializer.InitializeData(configuration);
}
}
}

View File

@@ -529,4 +529,14 @@ public enum UpdateVersion
/// The version of the <see cref="RepairImportedMapWarpsSeason6"/>.
/// </summary>
RepairImportedMapWarpsSeason6 = 104,
/// <summary>
/// The version of the <see cref="AddCastleSiegeDataUpdatePlugIn"/>.
/// </summary>
/// <remarks>
/// Upstream numbers this update 100. AdaMu already uses 95-104 for its own updates, so it is
/// renumbered to 105 here. Never reuse a number that has already shipped: the applied-update
/// bookkeeping is keyed on this value, so a collision would skip or re-run updates on live databases.
/// </remarks>
AddCastleSiegeData = 105,
}

View File

@@ -0,0 +1,228 @@
// <copyright file="CastleSiegeInitializer.cs" company="MUnique">
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
// </copyright>
namespace MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Events;
using MUnique.OpenMU.DataModel.Configuration;
using MUnique.OpenMU.DataModel.Entities;
using MUnique.OpenMU.Persistence.Initialization.VersionSeasonSix.Maps;
/// <summary>
/// Initializes the Castle Siege configuration and persistent state.
/// </summary>
internal sealed class CastleSiegeInitializer : InitializerBase
{
private const short GateMonsterNumber = 277;
private const short StatueMonsterNumber = 283;
/// <summary>
/// Initializes a new instance of the <see cref="CastleSiegeInitializer"/> class.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="gameConfiguration">The game configuration.</param>
public CastleSiegeInitializer(IContext context, GameConfiguration gameConfiguration)
: base(context, gameConfiguration)
{
}
/// <inheritdoc />
public override void Initialize()
{
var configuration = this.InitializeConfiguration();
this.InitializeData(configuration);
}
/// <summary>
/// Initializes the Castle Siege configuration, if it does not exist yet.
/// </summary>
/// <returns>The Castle Siege configuration.</returns>
internal CastleSiegeConfiguration InitializeConfiguration()
{
if (this.GameConfiguration.CastleSiegeConfiguration is { } existingConfiguration)
{
return existingConfiguration;
}
var configuration = this.Context.CreateNew<CastleSiegeConfiguration>();
configuration.Enabled = true;
configuration.CrownHoldTimeSeconds = 30;
configuration.RegisterMinLevel = 200;
configuration.RegisterMinMembers = 20;
configuration.ParticipantRewardMinSeconds = 60;
configuration.MaxAttackingGuilds = 3;
configuration.GuildScoreCastleSiege = 0;
configuration.GuildScoreCastleSiegeMembers = 0;
configuration.GateBuyPrice = 9_500_000;
configuration.StatueBuyPrice = 4_500_000;
configuration.CastleSiegeMapDefinition = this.GameConfiguration.Maps.Single(map => map.Number == ValleyOfLoren.Number);
configuration.LandOfTrialsMapDefinition = this.GameConfiguration.Maps.Single(map => map.Number == LandOfTrials.Number);
// AdaMu deliberately leaves StateSchedule empty. Upstream drives the cycle from a fixed weekly
// schedule; AdaMu drives it from CastleSiegeEventPlugIn (manual /cs commands, AdminPanel durations
// and the optional auto-open times in the plugin configuration). Nothing reads StateSchedule here.
this.InitializeNpcDefinitions(configuration);
this.InitializeUpgradeDefinitions(configuration);
this.InitializeMachineZones(configuration);
configuration.DefenseRespawnArea = this.CreateZone(74, 144, 115, 154);
configuration.AttackRespawnArea = this.CreateZone(35, 11, 144, 48);
this.GameConfiguration.CastleSiegeConfiguration = configuration;
return configuration;
}
/// <summary>
/// Initializes the persistent Castle Siege state.
/// </summary>
/// <param name="configuration">The Castle Siege configuration.</param>
/// <returns>The persistent Castle Siege state.</returns>
internal CastleSiegeData InitializeData(CastleSiegeConfiguration configuration)
{
var data = this.Context.CreateNew<CastleSiegeData>();
data.OwnerGuildId = null;
data.IsOccupied = false;
data.TaxChaos = 0;
data.TaxStore = 0;
data.TaxHunt = 0;
data.IsHuntZoneEnabled = false;
data.TributeMoney = 0;
var gateHitPoints = configuration.GateLifeUpgrades.Single(upgrade => upgrade.Level == 0).Value;
var statueHitPoints = configuration.StatueLifeUpgrades.Single(upgrade => upgrade.Level == 0).Value;
foreach (var npcDefinition in configuration.NpcDefinitions.Where(definition => definition.IsPersistedToDatabase))
{
var npcState = this.Context.CreateNew<CastleSiegeNpcState>();
npcState.MonsterNumber = npcDefinition.MonsterDefinition!.Number;
npcState.InstanceId = npcDefinition.InstanceId;
npcState.DefenseLevel = 0;
npcState.RegenLevel = 0;
npcState.LifeLevel = 0;
npcState.CurrentHp = npcState.MonsterNumber switch
{
GateMonsterNumber => gateHitPoints,
StatueMonsterNumber => statueHitPoints,
_ => throw new InvalidOperationException($"The persisted Castle Siege NPC monster number {npcState.MonsterNumber} is unsupported."),
};
data.NpcStates.Add(npcState);
}
return data;
}
private void InitializeNpcDefinitions(CastleSiegeConfiguration configuration)
{
this.AddNpc(configuration, 216, 1, false, CastleSiegeJoinSide.Attack1, 176, 212, Direction.SouthWest);
this.AddNpc(configuration, 217, 1, false, CastleSiegeJoinSide.Attack1, 167, 194, Direction.NorthWest);
this.AddNpc(configuration, 218, 1, false, CastleSiegeJoinSide.Attack1, 184, 195, Direction.NorthWest);
this.AddNpc(configuration, 219, 1, false, CastleSiegeJoinSide.Defense, 93, 208, Direction.SouthWest);
this.AddNpc(configuration, 219, 2, false, CastleSiegeJoinSide.Defense, 81, 165, Direction.SouthWest);
this.AddNpc(configuration, 219, 3, false, CastleSiegeJoinSide.Defense, 107, 165, Direction.SouthWest);
this.AddNpc(configuration, 219, 4, false, CastleSiegeJoinSide.Defense, 67, 118, Direction.SouthWest);
this.AddNpc(configuration, 219, 5, false, CastleSiegeJoinSide.Defense, 93, 118, Direction.SouthWest);
this.AddNpc(configuration, 219, 6, false, CastleSiegeJoinSide.Defense, 119, 118, Direction.SouthWest);
this.AddNpc(configuration, 221, 1, false, CastleSiegeJoinSide.Attack1, 63, 19, Direction.NorthEast);
this.AddNpc(configuration, 221, 2, false, CastleSiegeJoinSide.Attack1, 119, 19, Direction.NorthEast);
this.AddNpc(configuration, 222, 1, false, CastleSiegeJoinSide.Defense, 80, 188, Direction.SouthWest);
this.AddNpc(configuration, 222, 2, false, CastleSiegeJoinSide.Defense, 105, 188, Direction.SouthWest);
this.AddNpc(configuration, GateMonsterNumber, 1, true, CastleSiegeJoinSide.Defense, 93, 204, Direction.SouthWest);
this.AddNpc(configuration, GateMonsterNumber, 2, true, CastleSiegeJoinSide.Defense, 81, 161, Direction.SouthWest);
this.AddNpc(configuration, GateMonsterNumber, 3, true, CastleSiegeJoinSide.Defense, 107, 161, Direction.SouthWest);
this.AddNpc(configuration, GateMonsterNumber, 4, true, CastleSiegeJoinSide.Defense, 67, 114, Direction.SouthWest);
this.AddNpc(configuration, GateMonsterNumber, 5, true, CastleSiegeJoinSide.Defense, 93, 114, Direction.SouthWest);
this.AddNpc(configuration, GateMonsterNumber, 6, true, CastleSiegeJoinSide.Defense, 119, 114, Direction.SouthWest);
this.AddNpc(configuration, StatueMonsterNumber, 1, true, CastleSiegeJoinSide.Defense, 94, 227, Direction.SouthWest);
this.AddNpc(configuration, StatueMonsterNumber, 2, true, CastleSiegeJoinSide.Defense, 94, 182, Direction.SouthWest);
this.AddNpc(configuration, StatueMonsterNumber, 3, true, CastleSiegeJoinSide.Defense, 82, 130, Direction.SouthWest);
this.AddNpc(configuration, StatueMonsterNumber, 4, true, CastleSiegeJoinSide.Defense, 107, 130, Direction.SouthWest);
}
private void InitializeUpgradeDefinitions(CastleSiegeConfiguration configuration)
{
this.AddUpgrade(configuration.GateDefenseUpgrades, 0, 0, 0, 100);
this.AddUpgrade(configuration.GateDefenseUpgrades, 1, 2, 3_000_000, 180);
this.AddUpgrade(configuration.GateDefenseUpgrades, 2, 3, 3_000_000, 300);
this.AddUpgrade(configuration.GateDefenseUpgrades, 3, 4, 3_000_000, 520);
this.AddUpgrade(configuration.StatueDefenseUpgrades, 0, 0, 0, 80);
this.AddUpgrade(configuration.StatueDefenseUpgrades, 1, 3, 3_000_000, 180);
this.AddUpgrade(configuration.StatueDefenseUpgrades, 2, 5, 3_000_000, 340);
this.AddUpgrade(configuration.StatueDefenseUpgrades, 3, 7, 3_000_000, 550);
this.AddUpgrade(configuration.GateLifeUpgrades, 0, 0, 0, 1_900_000);
this.AddUpgrade(configuration.GateLifeUpgrades, 1, 2, 1_000_000, 2_500_000);
this.AddUpgrade(configuration.GateLifeUpgrades, 2, 3, 1_000_000, 3_500_000);
this.AddUpgrade(configuration.GateLifeUpgrades, 3, 4, 1_000_000, 5_200_000);
this.AddUpgrade(configuration.StatueLifeUpgrades, 0, 0, 0, 1_500_000);
this.AddUpgrade(configuration.StatueLifeUpgrades, 1, 3, 1_000_000, 2_200_000);
this.AddUpgrade(configuration.StatueLifeUpgrades, 2, 5, 1_000_000, 3_400_000);
this.AddUpgrade(configuration.StatueLifeUpgrades, 3, 7, 1_000_000, 5_000_000);
this.AddUpgrade(configuration.StatueRegenUpgrades, 0, 0, 0, 0);
this.AddUpgrade(configuration.StatueRegenUpgrades, 1, 3, 5_000_000, 1);
this.AddUpgrade(configuration.StatueRegenUpgrades, 2, 5, 5_000_000, 2);
this.AddUpgrade(configuration.StatueRegenUpgrades, 3, 7, 5_000_000, 3);
}
private void InitializeMachineZones(CastleSiegeConfiguration configuration)
{
configuration.AttackMachineZones.Add(this.CreateZone(62, 103, 72, 112));
configuration.AttackMachineZones.Add(this.CreateZone(88, 104, 124, 111));
configuration.AttackMachineZones.Add(this.CreateZone(116, 105, 124, 112));
configuration.AttackMachineZones.Add(this.CreateZone(73, 86, 105, 103));
configuration.DefenseMachineZones.Add(this.CreateZone(61, 88, 93, 108));
configuration.DefenseMachineZones.Add(this.CreateZone(92, 89, 127, 111));
configuration.DefenseMachineZones.Add(this.CreateZone(84, 52, 102, 66));
}
private void AddNpc(
CastleSiegeConfiguration configuration,
short monsterNumber,
byte instanceId,
bool isPersisted,
CastleSiegeJoinSide defaultSide,
byte spawnX,
byte spawnY,
Direction direction)
{
var definition = this.Context.CreateNew<CastleSiegeNpcDefinition>();
definition.MonsterDefinition = this.GameConfiguration.Monsters.Single(monster => monster.Number == monsterNumber);
definition.InstanceId = instanceId;
definition.IsPersistedToDatabase = isPersisted;
definition.DefaultSide = defaultSide;
definition.SpawnX = spawnX;
definition.SpawnY = spawnY;
definition.Direction = direction;
configuration.NpcDefinitions.Add(definition);
}
private void AddUpgrade(
ICollection<CastleSiegeUpgradeDefinition> target,
byte level,
int jewelCount,
int zen,
int value)
{
var upgrade = this.Context.CreateNew<CastleSiegeUpgradeDefinition>();
upgrade.Level = level;
upgrade.RequiredJewelOfGuardianCount = jewelCount;
upgrade.RequiredZen = zen;
upgrade.Value = value;
target.Add(upgrade);
}
private CastleSiegeZoneDefinition CreateZone(byte x1, byte y1, byte x2, byte y2)
{
var zone = this.Context.CreateNew<CastleSiegeZoneDefinition>();
zone.X1 = x1;
zone.Y1 = y1;
zone.X2 = x2;
zone.Y2 = y2;
return zone;
}
}

View File

@@ -89,6 +89,7 @@ public class GameConfigurationInitializer : GameConfigurationInitializerBase
new BloodCastleInitializer(this.Context, this.GameConfiguration).Initialize();
new ChaosCastleInitializer(this.Context, this.GameConfiguration).Initialize();
new HeykelSavasiInitializer(this.Context, this.GameConfiguration).Initialize();
new CastleSiegeInitializer(this.Context, this.GameConfiguration).Initialize();
}
private void CreateJewelMixes()