From ed67be0b3ce1a03aa58da702e5f1a9f670733c63 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 19:10:08 +0200 Subject: [PATCH 01/38] Add initial theme setup to the database --- .../Common/Interfaces/ICrpgDbContext.cs | 3 + src/Domain/Entities/Themes/Theme.cs | 25 + .../Entities/Themes/ThemeEquipmentSlot.cs | 17 + src/Domain/Entities/Themes/ThemeEvent.cs | 73 + .../Configurations/ThemeConfiguration.cs | 16 + .../Configurations/ThemeEventConfiguration.cs | 20 + src/Persistence/CrpgDbContext.cs | 5 +- src/Persistence/CrpgDbContextFactory.cs | 4 +- .../20260613165525_AddThemes.Designer.cs | 3317 +++++++++ .../Migrations/20260613165525_AddThemes.cs | 220 + .../Migrations/CrpgDbContextModelSnapshot.cs | 6517 +++++++++-------- 11 files changed, 7012 insertions(+), 3205 deletions(-) create mode 100644 src/Domain/Entities/Themes/Theme.cs create mode 100644 src/Domain/Entities/Themes/ThemeEquipmentSlot.cs create mode 100644 src/Domain/Entities/Themes/ThemeEvent.cs create mode 100644 src/Persistence/Configurations/ThemeConfiguration.cs create mode 100644 src/Persistence/Configurations/ThemeEventConfiguration.cs create mode 100644 src/Persistence/Migrations/20260613165525_AddThemes.Designer.cs create mode 100644 src/Persistence/Migrations/20260613165525_AddThemes.cs diff --git a/src/Application/Common/Interfaces/ICrpgDbContext.cs b/src/Application/Common/Interfaces/ICrpgDbContext.cs index 0d089385f..80de55ff1 100644 --- a/src/Application/Common/Interfaces/ICrpgDbContext.cs +++ b/src/Application/Common/Interfaces/ICrpgDbContext.cs @@ -13,6 +13,7 @@ using Crpg.Domain.Entities.Settings; using Crpg.Domain.Entities.Settlements; using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; using Crpg.Domain.Entities.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; @@ -60,6 +61,8 @@ public interface ICrpgDbContext DbSet QuestDefinitions { get; set; } DbSet UserQuests { get; set; } DbSet WeeklyQuestAssignments { get; set; } + DbSet Themes { get; set; } + DbSet ThemeEvents { get; set; } EntityEntry Entry(TEntity entity) where TEntity : class; Task SaveChangesAsync(CancellationToken cancellationToken = default); diff --git a/src/Domain/Entities/Themes/Theme.cs b/src/Domain/Entities/Themes/Theme.cs new file mode 100644 index 000000000..3af9283f9 --- /dev/null +++ b/src/Domain/Entities/Themes/Theme.cs @@ -0,0 +1,25 @@ +using Crpg.Domain.Common; + +namespace Crpg.Domain.Entities.Themes; + +public class Theme : AuditableEntity +{ + public Theme(string name) + { + Name = name; + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + // this contructor exists only because Ef core requires it. + private Theme() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + { + } + + public int Id { get; set; } + + /// + /// The name of the theme. + /// + public string Name { get; set; } +} diff --git a/src/Domain/Entities/Themes/ThemeEquipmentSlot.cs b/src/Domain/Entities/Themes/ThemeEquipmentSlot.cs new file mode 100644 index 000000000..affca83d0 --- /dev/null +++ b/src/Domain/Entities/Themes/ThemeEquipmentSlot.cs @@ -0,0 +1,17 @@ +namespace Crpg.Domain.Entities.Themes; + +public enum ThemeEquipmentSlot +{ + Head, + Shoulder, + Body, + Hand, + Leg, + MountHarness, + Mount, + Weapon0, + Weapon1, + Weapon2, + Weapon3, + WeaponExtra, +} diff --git a/src/Domain/Entities/Themes/ThemeEvent.cs b/src/Domain/Entities/Themes/ThemeEvent.cs new file mode 100644 index 000000000..5c76a97a2 --- /dev/null +++ b/src/Domain/Entities/Themes/ThemeEvent.cs @@ -0,0 +1,73 @@ +using Crpg.Domain.Common; + +namespace Crpg.Domain.Entities.Themes; + +public class ThemeEvent : AuditableEntity +{ + public ThemeEvent( + string name, + float goldMultiplier, + float expMultiplier, + DateTimeOffset activeFromUtc, + DateTimeOffset? activeUntilUtc, + List requiredEquipmentSlotsMatchingTheme, + Theme theme) + { + Name = name; + GoldMultiplier = goldMultiplier; + ExpMultiplier = expMultiplier; + ActiveFromUtc = activeFromUtc; + ActiveUntilUtc = activeUntilUtc; + RequiredEquipmentSlotsMatchingTheme = requiredEquipmentSlotsMatchingTheme; + EventTheme = theme; + } + +#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + // this contructor exists only because Ef core requires it. + private ThemeEvent() +#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable. + { + } + + public int Id { get; set; } + + /// + /// The name of the event. + /// + public string Name { get; set; } + + /// + /// The gold multiplier to apply to the rewards earned with this theme. + /// + public float GoldMultiplier { get; set; } = 1.0f; + + /// + /// The experience multiplier to apply to the rewards earned with this theme. + /// + public float ExpMultiplier { get; set; } = 1.0f; + + /// + /// The time from which the theme is active. + /// + public DateTimeOffset ActiveFromUtc { get; set; } + + /// + /// The time where the theme stops being active. If null, the theme is active indefinitely. + /// + public DateTimeOffset? ActiveUntilUtc { get; set; } + + /// + /// The equipment slots that must contain items matching the events theme for the player to be eligible for the event rewards. + /// + public List RequiredEquipmentSlotsMatchingTheme { get; set; } = new(); + + /// + /// The minimum amount of equipment slots that must contain items matching the events theme for the player to be eligible for the event rewards. + /// + public int MinumumRequiredEquipmentSlotsMatchingTheme { get; set; } + + /// + /// The theme of the event. + /// + public Theme EventTheme { get; set; } +} diff --git a/src/Persistence/Configurations/ThemeConfiguration.cs b/src/Persistence/Configurations/ThemeConfiguration.cs new file mode 100644 index 000000000..8137ae2d4 --- /dev/null +++ b/src/Persistence/Configurations/ThemeConfiguration.cs @@ -0,0 +1,16 @@ +using Crpg.Domain.Entities.Themes; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Crpg.Persistence.Configurations; + +public class ThemeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + builder.Property(x => x.Id).ValueGeneratedOnAdd(); + builder.HasIndex(x => x.Name); + builder.Property(x => x.Name).IsRequired().HasMaxLength(100); + } +} diff --git a/src/Persistence/Configurations/ThemeEventConfiguration.cs b/src/Persistence/Configurations/ThemeEventConfiguration.cs new file mode 100644 index 000000000..dceee30c0 --- /dev/null +++ b/src/Persistence/Configurations/ThemeEventConfiguration.cs @@ -0,0 +1,20 @@ +using Crpg.Domain.Entities.Themes; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Crpg.Persistence.Configurations; + +public class ThemeEventConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder.HasKey(x => x.Id); + builder.Property(x => x.Id).ValueGeneratedOnAdd(); + builder.HasIndex(x => x.Name); + builder.Property(x => x.Name).IsRequired().HasMaxLength(100); + builder.Property(x => x.ActiveFromUtc).IsRequired(); + builder.Property(x => x.MinumumRequiredEquipmentSlotsMatchingTheme).IsRequired(); + + builder.HasOne(x => x.EventTheme); + } +} diff --git a/src/Persistence/CrpgDbContext.cs b/src/Persistence/CrpgDbContext.cs index 1037910f0..394194d58 100644 --- a/src/Persistence/CrpgDbContext.cs +++ b/src/Persistence/CrpgDbContext.cs @@ -2,10 +2,10 @@ using Crpg.Application.Common.Interfaces; using Crpg.Domain.Common; using Crpg.Domain.Entities.ActivityLogs; -using Crpg.Domain.Entities.GameEvents; using Crpg.Domain.Entities.Battles; using Crpg.Domain.Entities.Characters; using Crpg.Domain.Entities.Clans; +using Crpg.Domain.Entities.GameEvents; using Crpg.Domain.Entities.Items; using Crpg.Domain.Entities.Limitations; using Crpg.Domain.Entities.Marketplace; @@ -16,6 +16,7 @@ using Crpg.Domain.Entities.Settings; using Crpg.Domain.Entities.Settlements; using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; using Crpg.Domain.Entities.Users; using Crpg.Sdk.Abstractions; using Microsoft.EntityFrameworkCore; @@ -78,6 +79,8 @@ public CrpgDbContext( public DbSet QuestDefinitions { get; set; } = default!; public DbSet UserQuests { get; set; } = default!; public DbSet WeeklyQuestAssignments { get; set; } = default!; + public DbSet Themes { get; set; } = default!; + public DbSet ThemeEvents { get; set; } = default!; public override async Task SaveChangesAsync(CancellationToken cancellationToken = default) { diff --git a/src/Persistence/CrpgDbContextFactory.cs b/src/Persistence/CrpgDbContextFactory.cs index 499bd8bf5..1d3a33b03 100644 --- a/src/Persistence/CrpgDbContextFactory.cs +++ b/src/Persistence/CrpgDbContextFactory.cs @@ -12,6 +12,7 @@ using Crpg.Domain.Entities.Servers; using Crpg.Domain.Entities.Settlements; using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; using Crpg.Domain.Entities.Users; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; @@ -61,7 +62,8 @@ public CrpgDbContext CreateDbContext(string[] args) .MapEnum() .MapEnum() .MapEnum() - .MapEnum()) + .MapEnum() + .MapEnum()) .UseSnakeCaseNamingConvention() .Options; return new CrpgDbContext(options); diff --git a/src/Persistence/Migrations/20260613165525_AddThemes.Designer.cs b/src/Persistence/Migrations/20260613165525_AddThemes.Designer.cs new file mode 100644 index 000000000..cee0d1b20 --- /dev/null +++ b/src/Persistence/Migrations/20260613165525_AddThemes.Designer.cs @@ -0,0 +1,3317 @@ +// +using System; +using System.Collections.Generic; +using Crpg.Domain.Entities; +using Crpg.Domain.Entities.ActivityLogs; +using Crpg.Domain.Entities.Battles; +using Crpg.Domain.Entities.Characters; +using Crpg.Domain.Entities.Clans; +using Crpg.Domain.Entities.Items; +using Crpg.Domain.Entities.Marketplace; +using Crpg.Domain.Entities.Notifications; +using Crpg.Domain.Entities.Parties; +using Crpg.Domain.Entities.Quests; +using Crpg.Domain.Entities.Restrictions; +using Crpg.Domain.Entities.Servers; +using Crpg.Domain.Entities.Settlements; +using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; +using Crpg.Domain.Entities.Users; +using Crpg.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetTopologySuite.Geometries; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Crpg.Persistence.Migrations +{ + [DbContext(typeof(CrpgDbContext))] + [Migration("20260613165525_AddThemes")] + partial class AddThemes + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "activity_log_type", new[] { "battle_apply_as_mercenary", "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked", "battle_participant_leaved", "character_created", "character_deleted", "character_earned", "character_rating_reset", "character_respecialized", "character_retired", "character_rewarded", "chat_message_sent", "clan_application_accepted", "clan_application_created", "clan_application_declined", "clan_armory_add_item", "clan_armory_borrow_item", "clan_armory_remove_item", "clan_armory_return_item", "clan_created", "clan_deleted", "clan_member_kicked", "clan_member_leaved", "clan_member_role_edited", "item_bought", "item_broke", "item_reforged", "item_repaired", "item_returned", "item_sold", "item_upgraded", "marketplace_listing_accepted", "marketplace_listing_cancelled", "marketplace_listing_created", "marketplace_listing_expired", "marketplace_listing_invalidated", "quest_rerolled", "quest_reward_claimed", "server_joined", "team_hit", "team_hit_reported", "team_hit_reported_user_kicked", "user_created", "user_deleted", "user_renamed", "user_rewarded" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_fighter_application_status", new[] { "accepted", "declined", "intent", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_mercenary_application_status", new[] { "accepted", "declined", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_participant_type", new[] { "clan_member", "mercenary", "party" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_phase", new[] { "end", "hiring", "live", "preparation", "scheduled" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_side", new[] { "attacker", "defender" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_class", new[] { "archer", "cavalry", "crossbowman", "infantry", "mounted_archer", "peasant", "shock_infantry", "skirmisher" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_status", new[] { "accepted", "declined", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_type", new[] { "offer", "request" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_member_role", new[] { "leader", "member", "officer" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "culture", new[] { "aserai", "battania", "empire", "khuzait", "looters", "neutral", "sturgia", "vlandia" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "damage_type", new[] { "blunt", "cut", "pierce", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "game_mode", new[] { "crpg_battle", "crpg_captain", "crpg_conquest", "crpg_duel", "crpg_siege", "crpg_skirmish", "crpg_team_deathmatch", "crpg_unknown_game_mode", "crpgdtv" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_type", new[] { "arrows", "banner", "body_armor", "bolts", "bow", "bullets", "crossbow", "hand_armor", "head_armor", "leg_armor", "mount", "mount_harness", "musket", "one_handed_weapon", "pistol", "polearm", "shield", "shoulder_armor", "thrown", "two_handed_weapon", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "languages", new[] { "be", "bg", "cs", "da", "de", "el", "en", "es", "fi", "fr", "hr", "hu", "it", "lv", "nl", "no", "pl", "pt", "ro", "ru", "sr", "sv", "tr", "uk", "zh" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "marketplace_listing_asset_side", new[] { "offered", "requested" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_state", new[] { "read", "unread" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_type", new[] { "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked_to_ex_participant", "character_rewarded_to_user", "clan_application_accepted_to_user", "clan_application_created_to_officers", "clan_application_created_to_user", "clan_application_declined_to_user", "clan_armory_borrow_item_to_lender", "clan_armory_remove_item_to_borrower", "clan_member_kicked_to_ex_member", "clan_member_leaved_to_leader", "clan_member_role_changed_to_user", "item_returned", "marketplace_listing_accepted_to_buyer", "marketplace_listing_accepted_to_seller", "marketplace_listing_expired", "marketplace_listing_invalidated", "user_rewarded_to_user" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_order_type", new[] { "attack_party", "attack_settlement", "follow_party", "join_battle", "move_to_point", "move_to_settlement", "transfer_offer_party" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_status", new[] { "awaiting_battle_join_decision", "awaiting_party_offer_decision", "idle", "idle_in_settlement", "in_battle", "recruiting_in_settlement" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_transfer_offer_status", new[] { "intent", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "platform", new[] { "epic_games", "microsoft", "steam" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_aggregation_type", new[] { "count", "sum" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_type", new[] { "daily", "weekly" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "region", new[] { "as", "eu", "na", "oc" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "restriction_type", new[] { "all", "chat", "join" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "role", new[] { "admin", "game_admin", "moderator", "user" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "settlement_type", new[] { "castle", "town", "village" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "terrain_type", new[] { "barrier", "deep_water", "plain", "shallow_water", "sparse_forest", "thick_forest" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "theme_equipment_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "weapon_class", new[] { "arrow", "banner", "bolt", "boulder", "bow", "cartridge", "crossbow", "dagger", "javelin", "large_shield", "low_grip_polearm", "mace", "musket", "one_handed_axe", "one_handed_polearm", "one_handed_sword", "pick", "pistol", "small_shield", "stone", "throwing_axe", "throwing_knife", "two_handed_axe", "two_handed_mace", "two_handed_polearm", "two_handed_sword", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("BattleParticipantStatistic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Assists") + .HasColumnType("integer") + .HasColumnName("assists"); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("Deaths") + .HasColumnType("integer") + .HasColumnName("deaths"); + + b.Property("Kills") + .HasColumnType("integer") + .HasColumnName("kills"); + + b.Property("ParticipantId") + .HasColumnType("integer") + .HasColumnName("participant_id"); + + b.Property("Participated") + .HasColumnType("boolean") + .HasColumnName("participated"); + + b.HasKey("Id") + .HasName("pk_battle_participant_statistic"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_participant_statistic_battle_id"); + + b.HasIndex("ParticipantId") + .IsUnique() + .HasDatabaseName("ix_battle_participant_statistic_participant_id"); + + b.ToTable("battle_participant_statistic", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Type") + .HasColumnType("activity_log_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_activity_logs"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_activity_logs_user_id"); + + b.HasIndex("CreatedAt", "UserId") + .HasDatabaseName("ix_activity_logs_created_at_user_id"); + + b.ToTable("activity_logs", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => + { + b.Property("ActivityLogId") + .HasColumnType("integer") + .HasColumnName("activity_log_id"); + + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("ActivityLogId", "Key") + .HasName("pk_activity_log_metadata"); + + b.ToTable("activity_log_metadata", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Phase") + .HasColumnType("battle_phase") + .HasColumnName("phase"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("ScheduledFor") + .HasColumnType("timestamp with time zone") + .HasColumnName("scheduled_for"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battles"); + + b.ToTable("battles", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("Commander") + .HasColumnType("boolean") + .HasColumnName("commander"); + + b.Property("ParticipantSlots") + .HasColumnType("integer") + .HasColumnName("participant_slots"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("SettlementId") + .HasColumnType("integer") + .HasColumnName("settlement_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.HasKey("Id") + .HasName("pk_battle_fighters"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_fighters_battle_id"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_battle_fighters_party_id"); + + b.HasIndex("SettlementId") + .HasDatabaseName("ix_battle_fighters_settlement_id"); + + b.ToTable("battle_fighters", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Status") + .HasColumnType("battle_fighter_application_status") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battle_fighter_applications"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_fighter_applications_battle_id"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_battle_fighter_applications_party_id"); + + b.ToTable("battle_fighter_applications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Status") + .HasColumnType("battle_mercenary_application_status") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Wage") + .HasColumnType("integer") + .HasColumnName("wage"); + + b.HasKey("Id") + .HasName("pk_battle_mercenary_applications"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_mercenary_applications_battle_id"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_battle_mercenary_applications_character_id"); + + b.ToTable("battle_mercenary_applications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CaptainFighterId") + .HasColumnType("integer") + .HasColumnName("captain_fighter_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("MercenaryApplicationId") + .HasColumnType("integer") + .HasColumnName("mercenary_application_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Type") + .HasColumnType("battle_participant_type") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_battle_participants"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_participants_battle_id"); + + b.HasIndex("CaptainFighterId") + .HasDatabaseName("ix_battle_participants_captain_fighter_id"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_battle_participants_character_id"); + + b.HasIndex("MercenaryApplicationId") + .HasDatabaseName("ix_battle_participants_mercenary_application_id"); + + b.ToTable("battle_participants", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battle_side_briefings"); + + b.HasIndex("BattleId", "Side") + .IsUnique() + .HasDatabaseName("ix_battle_side_briefings_battle_id_side"); + + b.ToTable("battle_side_briefings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Class") + .HasColumnType("character_class") + .HasColumnName("class"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("ForTournament") + .HasColumnType("boolean") + .HasColumnName("for_tournament"); + + b.Property("Generation") + .HasColumnType("integer") + .HasColumnName("generation"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_characters"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_characters_user_id"); + + b.ToTable("characters", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArmoryTimeout") + .HasColumnType("interval") + .HasColumnName("armory_timeout"); + + b.Property("BannerKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("banner_key"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Discord") + .HasColumnType("text") + .HasColumnName("discord"); + + b.PrimitiveCollection("Languages") + .IsRequired() + .HasColumnType("languages[]") + .HasColumnName("languages"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("PrimaryColor") + .HasColumnType("bigint") + .HasColumnName("primary_color"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("SecondaryColor") + .HasColumnType("bigint") + .HasColumnName("secondary_color"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tag"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_clans"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_clans_name"); + + b.HasIndex("Tag") + .IsUnique() + .HasDatabaseName("ix_clans_tag"); + + b.ToTable("clans", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("BorrowerClanId") + .HasColumnType("integer") + .HasColumnName("borrower_clan_id"); + + b.Property("BorrowerUserId") + .HasColumnType("integer") + .HasColumnName("borrower_user_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_clan_armory_borrowed_items"); + + b.HasIndex("BorrowerClanId") + .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_clan_id"); + + b.HasIndex("BorrowerUserId") + .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_user_id"); + + b.ToTable("clan_armory_borrowed_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClanId") + .HasColumnType("integer") + .HasColumnName("clan_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("InviteeId") + .HasColumnType("integer") + .HasColumnName("invitee_id"); + + b.Property("InviterId") + .HasColumnType("integer") + .HasColumnName("inviter_id"); + + b.Property("Status") + .HasColumnType("clan_invitation_status") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("clan_invitation_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_clan_invitations"); + + b.HasIndex("ClanId") + .HasDatabaseName("ix_clan_invitations_clan_id"); + + b.HasIndex("InviteeId") + .HasDatabaseName("ix_clan_invitations_invitee_id"); + + b.HasIndex("InviterId") + .HasDatabaseName("ix_clan_invitations_inviter_id"); + + b.ToTable("clan_invitations", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("ClanId") + .HasColumnType("integer") + .HasColumnName("clan_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Role") + .HasColumnType("clan_member_role") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserId") + .HasName("pk_clan_members"); + + b.HasIndex("ClanId") + .HasDatabaseName("ix_clan_members_clan_id"); + + b.ToTable("clan_members", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventData") + .HasColumnType("jsonb") + .HasColumnName("event_data"); + + b.Property("GameMode") + .HasColumnType("game_mode") + .HasColumnName("game_mode"); + + b.Property("Instance") + .IsRequired() + .HasColumnType("text") + .HasColumnName("instance"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_game_events"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("ix_game_events_created_at"); + + b.HasIndex("UserId", "Type", "CreatedAt") + .HasDatabaseName("ix_game_events_user_id_type_created_at"); + + b.ToTable("game_events", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("LenderClanId") + .HasColumnType("integer") + .HasColumnName("lender_clan_id"); + + b.Property("LenderUserId") + .HasColumnType("integer") + .HasColumnName("lender_user_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_clan_armory_items"); + + b.HasIndex("LenderClanId") + .HasDatabaseName("ix_clan_armory_items_lender_clan_id"); + + b.HasIndex("LenderUserId") + .HasDatabaseName("ix_clan_armory_items_lender_user_id"); + + b.ToTable("clan_armory_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Slot") + .HasColumnType("item_slot") + .HasColumnName("slot"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.HasKey("CharacterId", "Slot") + .HasName("pk_equipped_items"); + + b.HasIndex("UserItemId") + .HasDatabaseName("ix_equipped_items_user_item_id"); + + b.ToTable("equipped_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.Property("Id") + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("BaseId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("base_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Culture") + .HasColumnType("culture") + .HasColumnName("culture"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("Rank") + .HasColumnType("integer") + .HasColumnName("rank"); + + b.Property("Requirement") + .HasColumnType("integer") + .HasColumnName("requirement"); + + b.Property("Tier") + .HasColumnType("real") + .HasColumnName("tier"); + + b.Property("Type") + .HasColumnType("item_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Weight") + .HasColumnType("real") + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_items"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ItemId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("PartyTransferOfferId") + .HasColumnType("integer") + .HasColumnName("party_transfer_offer_id"); + + b.Property("SettlementId") + .HasColumnType("integer") + .HasColumnName("settlement_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_item_stacks"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_item_stacks_item_id"); + + b.HasIndex("PartyId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_party_id_item_id") + .HasFilter("party_id IS NOT NULL"); + + b.HasIndex("PartyTransferOfferId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_party_transfer_offer_id_item_id") + .HasFilter("party_transfer_offer_id IS NOT NULL"); + + b.HasIndex("SettlementId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_settlement_id_item_id") + .HasFilter("settlement_id IS NOT NULL"); + + b.ToTable("item_stacks", null, t => + { + t.HasCheckConstraint("CK_item_stacks_single_owner", "(party_id IS NOT NULL)::int + (settlement_id IS NOT NULL)::int + (party_transfer_offer_id IS NOT NULL)::int = 1"); + }); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_personal_items"); + + b.ToTable("personal_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("IsBroken") + .HasColumnType("boolean") + .HasColumnName("is_broken"); + + b.Property("ItemId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_items"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_user_items_item_id"); + + b.HasIndex("UserId", "ItemId") + .HasDatabaseName("ix_user_items_user_id_item_id"); + + b.ToTable("user_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_item_presets"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_item_presets_user_id"); + + b.ToTable("user_item_presets", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => + { + b.Property("UserItemPresetId") + .HasColumnType("integer") + .HasColumnName("user_item_preset_id"); + + b.Property("Slot") + .HasColumnType("item_slot") + .HasColumnName("slot"); + + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.HasKey("UserItemPresetId", "Slot") + .HasName("pk_user_item_preset_slots"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_user_item_preset_slots_item_id"); + + b.ToTable("user_item_preset_slots", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("LastRespecializeAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_respecialize_at"); + + b.HasKey("CharacterId") + .HasName("pk_character_limitations"); + + b.ToTable("character_limitations", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("GoldFee") + .HasColumnType("integer") + .HasColumnName("gold_fee"); + + b.Property("SellerId") + .HasColumnType("integer") + .HasColumnName("seller_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_marketplace_listings"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("ix_marketplace_listings_created_at"); + + b.HasIndex("ExpiresAt") + .HasDatabaseName("ix_marketplace_listings_expires_at"); + + b.HasIndex("SellerId", "CreatedAt") + .HasDatabaseName("ix_marketplace_listings_seller_id_created_at"); + + b.ToTable("marketplace_listings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("HeirloomPoints") + .HasColumnType("integer") + .HasColumnName("heirloom_points"); + + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("MarketplaceListingId") + .HasColumnType("integer") + .HasColumnName("marketplace_listing_id"); + + b.Property("Side") + .HasColumnType("marketplace_listing_asset_side") + .HasColumnName("side"); + + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.HasKey("Id") + .HasName("pk_marketplace_listing_assets"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_marketplace_listing_assets_item_id"); + + b.HasIndex("UserItemId") + .HasDatabaseName("ix_marketplace_listing_assets_user_item_id"); + + b.HasIndex("MarketplaceListingId", "Side") + .HasDatabaseName("ix_marketplace_listing_assets_marketplace_listing_id_side"); + + b.ToTable("marketplace_listing_assets", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("State") + .HasColumnType("notification_state") + .HasColumnName("state"); + + b.Property("Type") + .HasColumnType("notification_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_notifications"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_notifications_user_id"); + + b.ToTable("user_notifications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => + { + b.Property("UserNotificationId") + .HasColumnType("integer") + .HasColumnName("user_notification_id"); + + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("UserNotificationId", "Key") + .HasName("pk_user_notification_metadata"); + + b.ToTable("user_notification_metadata", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CurrentBattleId") + .HasColumnType("integer") + .HasColumnName("current_battle_id"); + + b.Property("CurrentPartyId") + .HasColumnType("integer") + .HasColumnName("current_party_id"); + + b.Property("CurrentSettlementId") + .HasColumnType("integer") + .HasColumnName("current_settlement_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Status") + .HasColumnType("party_status") + .HasColumnName("status"); + + b.Property("Troops") + .HasColumnType("real") + .HasColumnName("troops"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_parties"); + + b.HasIndex("CurrentBattleId") + .HasDatabaseName("ix_parties_current_battle_id"); + + b.HasIndex("CurrentPartyId") + .HasDatabaseName("ix_parties_current_party_id"); + + b.HasIndex("CurrentSettlementId") + .HasDatabaseName("ix_parties_current_settlement_id"); + + b.ToTable("parties", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderIndex") + .HasColumnType("integer") + .HasColumnName("order_index"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("TargetedBattleId") + .HasColumnType("integer") + .HasColumnName("targeted_battle_id"); + + b.Property("TargetedPartyId") + .HasColumnType("integer") + .HasColumnName("targeted_party_id"); + + b.Property("TargetedSettlementId") + .HasColumnType("integer") + .HasColumnName("targeted_settlement_id"); + + b.Property("Type") + .HasColumnType("party_order_type") + .HasColumnName("type"); + + b.Property("Waypoints") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("waypoints"); + + b.HasKey("Id") + .HasName("pk_party_orders"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_party_orders_party_id"); + + b.HasIndex("TargetedBattleId") + .HasDatabaseName("ix_party_orders_targeted_battle_id"); + + b.HasIndex("TargetedPartyId") + .HasDatabaseName("ix_party_orders_targeted_party_id"); + + b.HasIndex("TargetedSettlementId") + .HasDatabaseName("ix_party_orders_targeted_settlement_id"); + + b.ToTable("party_orders", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("Status") + .HasColumnType("party_transfer_offer_status") + .HasColumnName("status"); + + b.Property("TargetPartyId") + .HasColumnType("integer") + .HasColumnName("target_party_id"); + + b.Property("Troops") + .HasColumnType("real") + .HasColumnName("troops"); + + b.HasKey("Id") + .HasName("pk_party_transfer_offers"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_party_transfer_offers_party_id"); + + b.HasIndex("TargetPartyId") + .HasDatabaseName("ix_party_transfer_offers_target_party_id"); + + b.ToTable("party_transfer_offers", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.QuestDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AggregationField") + .HasColumnType("integer") + .HasColumnName("aggregation_field"); + + b.Property("AggregationType") + .HasColumnType("quest_aggregation_type") + .HasColumnName("aggregation_type"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventFiltersJson") + .HasColumnType("jsonb") + .HasColumnName("event_filters_json"); + + b.Property("EventType") + .HasColumnType("integer") + .HasColumnName("event_type"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("RequiredValue") + .HasColumnType("integer") + .HasColumnName("required_value"); + + b.Property("RewardExperience") + .HasColumnType("integer") + .HasColumnName("reward_experience"); + + b.Property("RewardGold") + .HasColumnType("integer") + .HasColumnName("reward_gold"); + + b.Property("Type") + .HasColumnType("quest_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_quest_definitions"); + + b.ToTable("quest_definitions", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("IsRewardClaimed") + .HasColumnType("boolean") + .HasColumnName("is_reward_claimed"); + + b.Property("QuestDefinitionId") + .HasColumnType("integer") + .HasColumnName("quest_definition_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_user_quests"); + + b.HasIndex("QuestDefinitionId") + .HasDatabaseName("ix_user_quests_quest_definition_id"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_quests_user_id"); + + b.ToTable("user_quests", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("QuestDefinitionId") + .HasColumnType("integer") + .HasColumnName("quest_definition_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_weekly_quest_assignments"); + + b.HasIndex("ExpiresAt") + .HasDatabaseName("ix_weekly_quest_assignments_expires_at"); + + b.HasIndex("QuestDefinitionId") + .HasDatabaseName("ix_weekly_quest_assignments_quest_definition_id"); + + b.ToTable("weekly_quest_assignments", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Duration") + .HasColumnType("interval") + .HasColumnName("duration"); + + b.Property("PublicReason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("public_reason"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RestrictedByUserId") + .HasColumnType("integer") + .HasColumnName("restricted_by_user_id"); + + b.Property("RestrictedUserId") + .HasColumnType("integer") + .HasColumnName("restricted_user_id"); + + b.Property("Type") + .HasColumnType("restriction_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_restrictions"); + + b.HasIndex("RestrictedByUserId") + .HasDatabaseName("ix_restrictions_restricted_by_user_id"); + + b.HasIndex("RestrictedUserId") + .HasDatabaseName("ix_restrictions_restricted_user_id"); + + b.ToTable("restrictions", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settings.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Discord") + .IsRequired() + .HasColumnType("text") + .HasColumnName("discord"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("HappyHours") + .IsRequired() + .HasColumnType("text") + .HasColumnName("happy_hours"); + + b.Property("ModDb") + .IsRequired() + .HasColumnType("text") + .HasColumnName("mod_db"); + + b.Property("Patreon") + .IsRequired() + .HasColumnType("text") + .HasColumnName("patreon"); + + b.Property("Reddit") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reddit"); + + b.Property("Steam") + .IsRequired() + .HasColumnType("text") + .HasColumnName("steam"); + + b.HasKey("Id") + .HasName("pk_settings"); + + b.ToTable("settings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Culture") + .HasColumnType("culture") + .HasColumnName("culture"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("owner_id"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("Scene") + .IsRequired() + .HasColumnType("text") + .HasColumnName("scene"); + + b.Property("Troops") + .HasColumnType("integer") + .HasColumnName("troops"); + + b.Property("Type") + .HasColumnType("settlement_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_settlements"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_settlements_owner_id"); + + b.HasIndex("Region", "Name") + .IsUnique() + .HasDatabaseName("ix_settlements_region_name"); + + b.ToTable("settlements", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Terrains.Terrain", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Boundary") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("boundary"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Type") + .HasColumnType("terrain_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_terrains"); + + b.ToTable("terrains", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_themes"); + + b.HasIndex("Name") + .HasDatabaseName("ix_themes_name"); + + b.ToTable("themes", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.ThemeEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveFromUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("active_from_utc"); + + b.Property("ActiveUntilUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("active_until_utc"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventThemeId") + .HasColumnType("integer") + .HasColumnName("event_theme_id"); + + b.Property("ExpMultiplier") + .HasColumnType("real") + .HasColumnName("exp_multiplier"); + + b.Property("GoldMultiplier") + .HasColumnType("real") + .HasColumnName("gold_multiplier"); + + b.Property("MinumumRequiredEquipmentSlotsMatchingTheme") + .HasColumnType("integer") + .HasColumnName("minumum_required_equipment_slots_matching_theme"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.PrimitiveCollection>("RequiredEquipmentSlotsMatchingTheme") + .IsRequired() + .HasColumnType("theme_equipment_slot[]") + .HasColumnName("required_equipment_slots_matching_theme"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_theme_events"); + + b.HasIndex("EventThemeId") + .HasDatabaseName("ix_theme_events_event_theme_id"); + + b.HasIndex("Name") + .HasDatabaseName("ix_theme_events_name"); + + b.ToTable("theme_events", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveCharacterId") + .HasColumnType("integer") + .HasColumnName("active_character_id"); + + b.Property("Avatar") + .HasColumnType("text") + .HasColumnName("avatar"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExperienceMultiplier") + .HasColumnType("real") + .HasColumnName("experience_multiplier"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("HeirloomPoints") + .HasColumnType("integer") + .HasColumnName("heirloom_points"); + + b.Property("IsDonor") + .HasColumnType("boolean") + .HasColumnName("is_donor"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Platform") + .HasColumnType("platform") + .HasColumnName("platform"); + + b.Property("PlatformUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("platform_user_id"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("Role") + .HasColumnType("role") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_users"); + + b.HasIndex("ActiveCharacterId") + .IsUnique() + .HasDatabaseName("ix_users_active_character_id"); + + b.HasIndex("Platform", "PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_users_platform_platform_user_id"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("BattleParticipantStatistic", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany() + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participant_statistic_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleParticipant", "Participant") + .WithOne("Statistic") + .HasForeignKey("BattleParticipantStatistic", "ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participant_statistic_battle_participants_participan"); + + b.Navigation("Battle"); + + b.Navigation("Participant"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_activity_logs_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => + { + b.HasOne("Crpg.Domain.Entities.ActivityLogs.ActivityLog", null) + .WithMany("Metadata") + .HasForeignKey("ActivityLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_activity_log_metadata_activity_logs_activity_log_id"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("Fighters") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighters_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .HasConstraintName("fk_battle_fighters_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") + .WithMany() + .HasForeignKey("SettlementId") + .HasConstraintName("fk_battle_fighters_settlements_settlement_id"); + + b.Navigation("Battle"); + + b.Navigation("Party"); + + b.Navigation("Settlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("FighterApplications") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighter_applications_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighter_applications_parties_party_id"); + + b.Navigation("Battle"); + + b.Navigation("Party"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("MercenaryApplications") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_mercenary_applications_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_mercenary_applications_characters_character_id"); + + b.Navigation("Battle"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("Participants") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleFighter", "CaptainFighter") + .WithMany() + .HasForeignKey("CaptainFighterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_battle_fighters_captain_fighter_id"); + + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_characters_character_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", "MercenaryApplication") + .WithMany() + .HasForeignKey("MercenaryApplicationId") + .HasConstraintName("fk_battle_participants_battle_mercenary_applications_mercenary"); + + b.Navigation("Battle"); + + b.Navigation("CaptainFighter"); + + b.Navigation("Character"); + + b.Navigation("MercenaryApplication"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("SideBriefings") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_side_briefings_battles_battle_id"); + + b.Navigation("Battle"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Characters") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_characters_users_user_id"); + + b.OwnsOne("Crpg.Domain.Entities.Characters.CharacterCharacteristics", "Characteristics", b1 => + { + b1.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b1.HasKey("CharacterId"); + + b1.ToTable("characters"); + + b1.WithOwner() + .HasForeignKey("CharacterId") + .HasConstraintName("fk_characters_characters_id"); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterAttributes", "Attributes", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Agility") + .HasColumnType("integer") + .HasColumnName("agility"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("attribute_points"); + + b2.Property("Strength") + .HasColumnType("integer") + .HasColumnName("strength"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterSkills", "Skills", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Athletics") + .HasColumnType("integer") + .HasColumnName("athletics"); + + b2.Property("IronFlesh") + .HasColumnType("integer") + .HasColumnName("iron_flesh"); + + b2.Property("MountedArchery") + .HasColumnType("integer") + .HasColumnName("mounted_archery"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("skill_points"); + + b2.Property("PowerDraw") + .HasColumnType("integer") + .HasColumnName("power_draw"); + + b2.Property("PowerStrike") + .HasColumnType("integer") + .HasColumnName("power_strike"); + + b2.Property("PowerThrow") + .HasColumnType("integer") + .HasColumnName("power_throw"); + + b2.Property("Riding") + .HasColumnType("integer") + .HasColumnName("riding"); + + b2.Property("Shield") + .HasColumnType("integer") + .HasColumnName("shield"); + + b2.Property("WeaponMaster") + .HasColumnType("integer") + .HasColumnName("weapon_master"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterWeaponProficiencies", "WeaponProficiencies", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Bow") + .HasColumnType("integer") + .HasColumnName("bow"); + + b2.Property("Crossbow") + .HasColumnType("integer") + .HasColumnName("crossbow"); + + b2.Property("OneHanded") + .HasColumnType("integer") + .HasColumnName("one_handed"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("weapon_proficiency_points"); + + b2.Property("Polearm") + .HasColumnType("integer") + .HasColumnName("polearm"); + + b2.Property("Throwing") + .HasColumnType("integer") + .HasColumnName("throwing"); + + b2.Property("TwoHanded") + .HasColumnType("integer") + .HasColumnName("two_handed"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.Navigation("Attributes") + .IsRequired(); + + b1.Navigation("Skills") + .IsRequired(); + + b1.Navigation("WeaponProficiencies") + .IsRequired(); + }); + + b.OwnsMany("Crpg.Domain.Entities.Characters.CharacterStatistics", "Statistics", b1 => + { + b1.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Assists") + .HasColumnType("integer") + .HasColumnName("assists"); + + b1.Property("Deaths") + .HasColumnType("integer") + .HasColumnName("deaths"); + + b1.Property("GameMode") + .HasColumnType("game_mode") + .HasColumnName("game_mode"); + + b1.Property("Kills") + .HasColumnType("integer") + .HasColumnName("kills"); + + b1.Property("PlayTime") + .HasColumnType("interval") + .HasColumnName("play_time"); + + b1.HasKey("CharacterId", "Id") + .HasName("pk_character_statistics"); + + b1.ToTable("character_statistics", (string)null); + + b1.WithOwner("Character") + .HasForeignKey("CharacterId") + .HasConstraintName("fk_character_statistics_characters_character_id"); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterRating", "Rating", b2 => + { + b2.Property("CharacterStatisticsCharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b2.Property("CharacterStatisticsId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("CompetitiveValue") + .HasColumnType("real") + .HasColumnName("competitive_rating"); + + b2.Property("Deviation") + .HasColumnType("real") + .HasColumnName("rating_deviation"); + + b2.Property("Value") + .HasColumnType("real") + .HasColumnName("rating"); + + b2.Property("Volatility") + .HasColumnType("real") + .HasColumnName("rating_volatility"); + + b2.HasKey("CharacterStatisticsCharacterId", "CharacterStatisticsId"); + + b2.ToTable("character_statistics"); + + b2.WithOwner() + .HasForeignKey("CharacterStatisticsCharacterId", "CharacterStatisticsId") + .HasConstraintName("fk_character_statistics_character_statistics_character_id_id"); + }); + + b1.Navigation("Character"); + + b1.Navigation("Rating") + .IsRequired(); + }); + + b.Navigation("Characteristics") + .IsRequired(); + + b.Navigation("Statistics"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("ArmoryBorrowedItems") + .HasForeignKey("BorrowerClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clans_borrower_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Borrower") + .WithMany("ArmoryBorrowedItems") + .HasForeignKey("BorrowerUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clan_members_borrower_user_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("ClanArmoryBorrowedItem") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_user_items_user_item_id"); + + b.HasOne("Crpg.Domain.Entities.Items.ClanArmoryItem", "ArmoryItem") + .WithOne("BorrowedItem") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clan_armory_items_user_item_id"); + + b.Navigation("ArmoryItem"); + + b.Navigation("Borrower"); + + b.Navigation("Clan"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("Invitations") + .HasForeignKey("ClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_clans_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "Invitee") + .WithMany() + .HasForeignKey("InviteeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_users_invitee_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "Inviter") + .WithMany() + .HasForeignKey("InviterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_users_inviter_id"); + + b.Navigation("Clan"); + + b.Navigation("Invitee"); + + b.Navigation("Inviter"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("Members") + .HasForeignKey("ClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_members_clans_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithOne("ClanMembership") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanMember", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_members_users_user_id"); + + b.Navigation("Clan"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_game_events_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("ArmoryItems") + .HasForeignKey("LenderClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_clans_lender_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Lender") + .WithMany("ArmoryItems") + .HasForeignKey("LenderUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_clan_members_lender_user_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("ClanArmoryItem") + .HasForeignKey("Crpg.Domain.Entities.Items.ClanArmoryItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_user_items_user_item_id"); + + b.Navigation("Clan"); + + b.Navigation("Lender"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany("EquippedItems") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_equipped_items_characters_character_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithMany("EquippedItems") + .HasForeignKey("UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_equipped_items_user_items_user_item_id"); + + b.Navigation("Character"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "PrimaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("primary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("primary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("primary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("primary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("primary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("primary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("primary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("primary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("primary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("primary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("primary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("primary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("primary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("primary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("primary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("primary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "SecondaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("secondary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("secondary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("secondary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("secondary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("secondary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("secondary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("secondary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("secondary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("secondary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("secondary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("secondary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("secondary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("secondary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "TertiaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("tertiary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("tertiary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("tertiary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("tertiary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("tertiary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("tertiary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tertiary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("tertiary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("tertiary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("tertiary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("tertiary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("tertiary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("tertiary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemArmorComponent", "Armor", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("ArmArmor") + .HasColumnType("integer") + .HasColumnName("armor_arm"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("armor_body"); + + b1.Property("FamilyType") + .HasColumnType("integer") + .HasColumnName("armor_family_type"); + + b1.Property("HeadArmor") + .HasColumnType("integer") + .HasColumnName("armor_head"); + + b1.Property("LegArmor") + .HasColumnType("integer") + .HasColumnName("armor_leg"); + + b1.Property("MaterialType") + .HasColumnType("integer") + .HasColumnName("armor_material_type"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemMountComponent", "Mount", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("BodyLength") + .HasColumnType("integer") + .HasColumnName("mount_body_length"); + + b1.Property("ChargeDamage") + .HasColumnType("integer") + .HasColumnName("mount_charge_damage"); + + b1.Property("FamilyType") + .HasColumnType("integer") + .HasColumnName("mount_family_type"); + + b1.Property("HitPoints") + .HasColumnType("integer") + .HasColumnName("mount_hit_points"); + + b1.Property("Maneuver") + .HasColumnType("integer") + .HasColumnName("mount_maneuver"); + + b1.Property("Speed") + .HasColumnType("integer") + .HasColumnName("mount_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.Navigation("Armor"); + + b.Navigation("Mount"); + + b.Navigation("PrimaryWeapon"); + + b.Navigation("SecondaryWeapon"); + + b.Navigation("TertiaryWeapon"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_stacks_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany("Items") + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.PartyTransferOffer", "PartyTransferOffer") + .WithMany("Items") + .HasForeignKey("PartyTransferOfferId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_party_transfer_offers_party_transfer_offer_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") + .WithMany("Items") + .HasForeignKey("SettlementId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_settlements_settlement_id"); + + b.Navigation("Item"); + + b.Navigation("Party"); + + b.Navigation("PartyTransferOffer"); + + b.Navigation("Settlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => + { + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("PersonalItem") + .HasForeignKey("Crpg.Domain.Entities.Items.PersonalItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_personal_items_user_items_user_item_id"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany("UserItems") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_items_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Items") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_items_users_user_id"); + + b.Navigation("Item"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("ItemPresets") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_item_presets_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_user_item_preset_slots_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItemPreset", "UserItemPreset") + .WithMany("Slots") + .HasForeignKey("UserItemPresetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_item_preset_slots_user_item_presets_user_item_preset_id"); + + b.Navigation("Item"); + + b.Navigation("UserItemPreset"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithOne("Limitations") + .HasForeignKey("Crpg.Domain.Entities.Limitations.CharacterLimitations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_character_limitations_characters_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "Seller") + .WithMany("MarketplaceListings") + .HasForeignKey("SellerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_marketplace_listings_users_seller_id"); + + b.Navigation("Seller"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .HasConstraintName("fk_marketplace_listing_assets_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Marketplace.MarketplaceListing", "MarketplaceListing") + .WithMany("Assets") + .HasForeignKey("MarketplaceListingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_marketplace_listing_assets_marketplace_listings_marketplace"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithMany("MarketplaceListingAssets") + .HasForeignKey("UserItemId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_marketplace_listing_assets_user_items_user_item_id"); + + b.Navigation("Item"); + + b.Navigation("MarketplaceListing"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Notifications") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_notifications_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => + { + b.HasOne("Crpg.Domain.Entities.Notifications.UserNotification", null) + .WithMany("Metadata") + .HasForeignKey("UserNotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_notification_metadata_user_notifications_user_notifica"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "CurrentBattle") + .WithMany() + .HasForeignKey("CurrentBattleId") + .HasConstraintName("fk_parties_battles_current_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "CurrentParty") + .WithMany() + .HasForeignKey("CurrentPartyId") + .HasConstraintName("fk_parties_parties_current_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "CurrentSettlement") + .WithMany() + .HasForeignKey("CurrentSettlementId") + .HasConstraintName("fk_parties_settlements_current_settlement_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithOne("Party") + .HasForeignKey("Crpg.Domain.Entities.Parties.Party", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_parties_users_id"); + + b.Navigation("CurrentBattle"); + + b.Navigation("CurrentParty"); + + b.Navigation("CurrentSettlement"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany("Orders") + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_orders_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "TargetedBattle") + .WithMany() + .HasForeignKey("TargetedBattleId") + .HasConstraintName("fk_party_orders_battles_targeted_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetedParty") + .WithMany() + .HasForeignKey("TargetedPartyId") + .HasConstraintName("fk_party_orders_parties_targeted_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "TargetedSettlement") + .WithMany() + .HasForeignKey("TargetedSettlementId") + .HasConstraintName("fk_party_orders_settlements_targeted_settlement_id"); + + b.Navigation("Party"); + + b.Navigation("TargetedBattle"); + + b.Navigation("TargetedParty"); + + b.Navigation("TargetedSettlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_transfer_offers_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetParty") + .WithMany() + .HasForeignKey("TargetPartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_transfer_offers_parties_target_party_id"); + + b.Navigation("Party"); + + b.Navigation("TargetParty"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => + { + b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") + .WithMany() + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_user_quests_quest_definitions_quest_definition_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_quests_users_user_id"); + + b.Navigation("QuestDefinition"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => + { + b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") + .WithMany() + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_weekly_quest_assignments_quest_definitions_quest_definition"); + + b.Navigation("QuestDefinition"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedByUser") + .WithMany() + .HasForeignKey("RestrictedByUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_restrictions_users_restricted_by_user_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedUser") + .WithMany("Restrictions") + .HasForeignKey("RestrictedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_restrictions_users_restricted_user_id"); + + b.Navigation("RestrictedByUser"); + + b.Navigation("RestrictedUser"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Owner") + .WithMany("OwnedSettlements") + .HasForeignKey("OwnerId") + .HasConstraintName("fk_settlements_parties_owner_id"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.ThemeEvent", b => + { + b.HasOne("Crpg.Domain.Entities.Themes.Theme", "EventTheme") + .WithMany() + .HasForeignKey("EventThemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_theme_events_themes_event_theme_id"); + + b.Navigation("EventTheme"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "ActiveCharacter") + .WithOne() + .HasForeignKey("Crpg.Domain.Entities.Users.User", "ActiveCharacterId") + .HasConstraintName("fk_users_characters_active_character_id"); + + b.Navigation("ActiveCharacter"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.Navigation("Metadata"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => + { + b.Navigation("FighterApplications"); + + b.Navigation("Fighters"); + + b.Navigation("MercenaryApplications"); + + b.Navigation("Participants"); + + b.Navigation("SideBriefings"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.Navigation("Statistic"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.Navigation("EquippedItems"); + + b.Navigation("Limitations"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => + { + b.Navigation("ArmoryBorrowedItems"); + + b.Navigation("ArmoryItems"); + + b.Navigation("Invitations"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.Navigation("ArmoryBorrowedItems"); + + b.Navigation("ArmoryItems"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.Navigation("BorrowedItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.Navigation("UserItems"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.Navigation("ClanArmoryBorrowedItem"); + + b.Navigation("ClanArmoryItem"); + + b.Navigation("EquippedItems"); + + b.Navigation("MarketplaceListingAssets"); + + b.Navigation("PersonalItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.Navigation("Slots"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.Navigation("Assets"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.Navigation("Metadata"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + + b.Navigation("OwnedSettlements"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.Navigation("Characters"); + + b.Navigation("ClanMembership"); + + b.Navigation("ItemPresets"); + + b.Navigation("Items"); + + b.Navigation("MarketplaceListings"); + + b.Navigation("Notifications"); + + b.Navigation("Party"); + + b.Navigation("Restrictions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Persistence/Migrations/20260613165525_AddThemes.cs b/src/Persistence/Migrations/20260613165525_AddThemes.cs new file mode 100644 index 000000000..d666a7f4d --- /dev/null +++ b/src/Persistence/Migrations/20260613165525_AddThemes.cs @@ -0,0 +1,220 @@ +using System; +using System.Collections.Generic; +using Crpg.Domain.Entities.Themes; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Crpg.Persistence.Migrations +{ + /// + public partial class AddThemes : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterDatabase() + .Annotation("Npgsql:Enum:activity_log_type", "battle_apply_as_mercenary,battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked,battle_participant_leaved,character_created,character_deleted,character_earned,character_rating_reset,character_respecialized,character_retired,character_rewarded,chat_message_sent,clan_application_accepted,clan_application_created,clan_application_declined,clan_armory_add_item,clan_armory_borrow_item,clan_armory_remove_item,clan_armory_return_item,clan_created,clan_deleted,clan_member_kicked,clan_member_leaved,clan_member_role_edited,item_bought,item_broke,item_reforged,item_repaired,item_returned,item_sold,item_upgraded,marketplace_listing_accepted,marketplace_listing_cancelled,marketplace_listing_created,marketplace_listing_expired,marketplace_listing_invalidated,quest_rerolled,quest_reward_claimed,server_joined,team_hit,team_hit_reported,team_hit_reported_user_kicked,user_created,user_deleted,user_renamed,user_rewarded") + .Annotation("Npgsql:Enum:battle_fighter_application_status", "accepted,declined,intent,pending") + .Annotation("Npgsql:Enum:battle_mercenary_application_status", "accepted,declined,pending") + .Annotation("Npgsql:Enum:battle_participant_type", "clan_member,mercenary,party") + .Annotation("Npgsql:Enum:battle_phase", "end,hiring,live,preparation,scheduled") + .Annotation("Npgsql:Enum:battle_side", "attacker,defender") + .Annotation("Npgsql:Enum:character_class", "archer,cavalry,crossbowman,infantry,mounted_archer,peasant,shock_infantry,skirmisher") + .Annotation("Npgsql:Enum:clan_invitation_status", "accepted,declined,pending") + .Annotation("Npgsql:Enum:clan_invitation_type", "offer,request") + .Annotation("Npgsql:Enum:clan_member_role", "leader,member,officer") + .Annotation("Npgsql:Enum:culture", "aserai,battania,empire,khuzait,looters,neutral,sturgia,vlandia") + .Annotation("Npgsql:Enum:damage_type", "blunt,cut,pierce,undefined") + .Annotation("Npgsql:Enum:game_mode", "crpg_battle,crpg_captain,crpg_conquest,crpg_duel,crpg_siege,crpg_skirmish,crpg_team_deathmatch,crpg_unknown_game_mode,crpgdtv") + .Annotation("Npgsql:Enum:item_slot", "body,hand,head,leg,mount,mount_harness,shoulder,weapon0,weapon1,weapon2,weapon3,weapon_extra") + .Annotation("Npgsql:Enum:item_type", "arrows,banner,body_armor,bolts,bow,bullets,crossbow,hand_armor,head_armor,leg_armor,mount,mount_harness,musket,one_handed_weapon,pistol,polearm,shield,shoulder_armor,thrown,two_handed_weapon,undefined") + .Annotation("Npgsql:Enum:languages", "be,bg,cs,da,de,el,en,es,fi,fr,hr,hu,it,lv,nl,no,pl,pt,ro,ru,sr,sv,tr,uk,zh") + .Annotation("Npgsql:Enum:marketplace_listing_asset_side", "offered,requested") + .Annotation("Npgsql:Enum:notification_state", "read,unread") + .Annotation("Npgsql:Enum:notification_type", "battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked_to_ex_participant,character_rewarded_to_user,clan_application_accepted_to_user,clan_application_created_to_officers,clan_application_created_to_user,clan_application_declined_to_user,clan_armory_borrow_item_to_lender,clan_armory_remove_item_to_borrower,clan_member_kicked_to_ex_member,clan_member_leaved_to_leader,clan_member_role_changed_to_user,item_returned,marketplace_listing_accepted_to_buyer,marketplace_listing_accepted_to_seller,marketplace_listing_expired,marketplace_listing_invalidated,user_rewarded_to_user") + .Annotation("Npgsql:Enum:party_order_type", "attack_party,attack_settlement,follow_party,join_battle,move_to_point,move_to_settlement,transfer_offer_party") + .Annotation("Npgsql:Enum:party_status", "awaiting_battle_join_decision,awaiting_party_offer_decision,idle,idle_in_settlement,in_battle,recruiting_in_settlement") + .Annotation("Npgsql:Enum:party_transfer_offer_status", "intent,pending") + .Annotation("Npgsql:Enum:platform", "epic_games,microsoft,steam") + .Annotation("Npgsql:Enum:quest_aggregation_type", "count,sum") + .Annotation("Npgsql:Enum:quest_type", "daily,weekly") + .Annotation("Npgsql:Enum:region", "as,eu,na,oc") + .Annotation("Npgsql:Enum:restriction_type", "all,chat,join") + .Annotation("Npgsql:Enum:role", "admin,game_admin,moderator,user") + .Annotation("Npgsql:Enum:settlement_type", "castle,town,village") + .Annotation("Npgsql:Enum:terrain_type", "barrier,deep_water,plain,shallow_water,sparse_forest,thick_forest") + .Annotation("Npgsql:Enum:theme_equipment_slot", "body,hand,head,leg,mount,mount_harness,shoulder,weapon0,weapon1,weapon2,weapon3,weapon_extra") + .Annotation("Npgsql:Enum:weapon_class", "arrow,banner,bolt,boulder,bow,cartridge,crossbow,dagger,javelin,large_shield,low_grip_polearm,mace,musket,one_handed_axe,one_handed_polearm,one_handed_sword,pick,pistol,small_shield,stone,throwing_axe,throwing_knife,two_handed_axe,two_handed_mace,two_handed_polearm,two_handed_sword,undefined") + .Annotation("Npgsql:PostgresExtension:postgis", ",,") + .OldAnnotation("Npgsql:Enum:activity_log_type", "battle_apply_as_mercenary,battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked,battle_participant_leaved,character_created,character_deleted,character_earned,character_rating_reset,character_respecialized,character_retired,character_rewarded,chat_message_sent,clan_application_accepted,clan_application_created,clan_application_declined,clan_armory_add_item,clan_armory_borrow_item,clan_armory_remove_item,clan_armory_return_item,clan_created,clan_deleted,clan_member_kicked,clan_member_leaved,clan_member_role_edited,item_bought,item_broke,item_reforged,item_repaired,item_returned,item_sold,item_upgraded,marketplace_listing_accepted,marketplace_listing_cancelled,marketplace_listing_created,marketplace_listing_expired,marketplace_listing_invalidated,quest_rerolled,quest_reward_claimed,server_joined,team_hit,team_hit_reported,team_hit_reported_user_kicked,user_created,user_deleted,user_renamed,user_rewarded") + .OldAnnotation("Npgsql:Enum:battle_fighter_application_status", "accepted,declined,intent,pending") + .OldAnnotation("Npgsql:Enum:battle_mercenary_application_status", "accepted,declined,pending") + .OldAnnotation("Npgsql:Enum:battle_participant_type", "clan_member,mercenary,party") + .OldAnnotation("Npgsql:Enum:battle_phase", "end,hiring,live,preparation,scheduled") + .OldAnnotation("Npgsql:Enum:battle_side", "attacker,defender") + .OldAnnotation("Npgsql:Enum:character_class", "archer,cavalry,crossbowman,infantry,mounted_archer,peasant,shock_infantry,skirmisher") + .OldAnnotation("Npgsql:Enum:clan_invitation_status", "accepted,declined,pending") + .OldAnnotation("Npgsql:Enum:clan_invitation_type", "offer,request") + .OldAnnotation("Npgsql:Enum:clan_member_role", "leader,member,officer") + .OldAnnotation("Npgsql:Enum:culture", "aserai,battania,empire,khuzait,looters,neutral,sturgia,vlandia") + .OldAnnotation("Npgsql:Enum:damage_type", "blunt,cut,pierce,undefined") + .OldAnnotation("Npgsql:Enum:game_mode", "crpg_battle,crpg_captain,crpg_conquest,crpg_duel,crpg_siege,crpg_skirmish,crpg_team_deathmatch,crpg_unknown_game_mode,crpgdtv") + .OldAnnotation("Npgsql:Enum:item_slot", "body,hand,head,leg,mount,mount_harness,shoulder,weapon0,weapon1,weapon2,weapon3,weapon_extra") + .OldAnnotation("Npgsql:Enum:item_type", "arrows,banner,body_armor,bolts,bow,bullets,crossbow,hand_armor,head_armor,leg_armor,mount,mount_harness,musket,one_handed_weapon,pistol,polearm,shield,shoulder_armor,thrown,two_handed_weapon,undefined") + .OldAnnotation("Npgsql:Enum:languages", "be,bg,cs,da,de,el,en,es,fi,fr,hr,hu,it,lv,nl,no,pl,pt,ro,ru,sr,sv,tr,uk,zh") + .OldAnnotation("Npgsql:Enum:marketplace_listing_asset_side", "offered,requested") + .OldAnnotation("Npgsql:Enum:notification_state", "read,unread") + .OldAnnotation("Npgsql:Enum:notification_type", "battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked_to_ex_participant,character_rewarded_to_user,clan_application_accepted_to_user,clan_application_created_to_officers,clan_application_created_to_user,clan_application_declined_to_user,clan_armory_borrow_item_to_lender,clan_armory_remove_item_to_borrower,clan_member_kicked_to_ex_member,clan_member_leaved_to_leader,clan_member_role_changed_to_user,item_returned,marketplace_listing_accepted_to_buyer,marketplace_listing_accepted_to_seller,marketplace_listing_expired,marketplace_listing_invalidated,user_rewarded_to_user") + .OldAnnotation("Npgsql:Enum:party_order_type", "attack_party,attack_settlement,follow_party,join_battle,move_to_point,move_to_settlement,transfer_offer_party") + .OldAnnotation("Npgsql:Enum:party_status", "awaiting_battle_join_decision,awaiting_party_offer_decision,idle,idle_in_settlement,in_battle,recruiting_in_settlement") + .OldAnnotation("Npgsql:Enum:party_transfer_offer_status", "intent,pending") + .OldAnnotation("Npgsql:Enum:platform", "epic_games,microsoft,steam") + .OldAnnotation("Npgsql:Enum:quest_aggregation_type", "count,sum") + .OldAnnotation("Npgsql:Enum:quest_type", "daily,weekly") + .OldAnnotation("Npgsql:Enum:region", "as,eu,na,oc") + .OldAnnotation("Npgsql:Enum:restriction_type", "all,chat,join") + .OldAnnotation("Npgsql:Enum:role", "admin,game_admin,moderator,user") + .OldAnnotation("Npgsql:Enum:settlement_type", "castle,town,village") + .OldAnnotation("Npgsql:Enum:terrain_type", "barrier,deep_water,plain,shallow_water,sparse_forest,thick_forest") + .OldAnnotation("Npgsql:Enum:weapon_class", "arrow,banner,bolt,boulder,bow,cartridge,crossbow,dagger,javelin,large_shield,low_grip_polearm,mace,musket,one_handed_axe,one_handed_polearm,one_handed_sword,pick,pistol,small_shield,stone,throwing_axe,throwing_knife,two_handed_axe,two_handed_mace,two_handed_polearm,two_handed_sword,undefined") + .OldAnnotation("Npgsql:PostgresExtension:postgis", ",,"); + + migrationBuilder.CreateTable( + name: "themes", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_themes", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "theme_events", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + name = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + gold_multiplier = table.Column(type: "real", nullable: false), + exp_multiplier = table.Column(type: "real", nullable: false), + active_from_utc = table.Column(type: "timestamp with time zone", nullable: false), + active_until_utc = table.Column(type: "timestamp with time zone", nullable: true), + required_equipment_slots_matching_theme = table.Column>(type: "theme_equipment_slot[]", nullable: false), + minumum_required_equipment_slots_matching_theme = table.Column(type: "integer", nullable: false), + event_theme_id = table.Column(type: "integer", nullable: false), + updated_at = table.Column(type: "timestamp with time zone", nullable: false), + created_at = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_theme_events", x => x.id); + table.ForeignKey( + name: "fk_theme_events_themes_event_theme_id", + column: x => x.event_theme_id, + principalTable: "themes", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_theme_events_event_theme_id", + table: "theme_events", + column: "event_theme_id"); + + migrationBuilder.CreateIndex( + name: "ix_theme_events_name", + table: "theme_events", + column: "name"); + + migrationBuilder.CreateIndex( + name: "ix_themes_name", + table: "themes", + column: "name"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "theme_events"); + + migrationBuilder.DropTable( + name: "themes"); + + migrationBuilder.AlterDatabase() + .Annotation("Npgsql:Enum:activity_log_type", "battle_apply_as_mercenary,battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked,battle_participant_leaved,character_created,character_deleted,character_earned,character_rating_reset,character_respecialized,character_retired,character_rewarded,chat_message_sent,clan_application_accepted,clan_application_created,clan_application_declined,clan_armory_add_item,clan_armory_borrow_item,clan_armory_remove_item,clan_armory_return_item,clan_created,clan_deleted,clan_member_kicked,clan_member_leaved,clan_member_role_edited,item_bought,item_broke,item_reforged,item_repaired,item_returned,item_sold,item_upgraded,marketplace_listing_accepted,marketplace_listing_cancelled,marketplace_listing_created,marketplace_listing_expired,marketplace_listing_invalidated,quest_rerolled,quest_reward_claimed,server_joined,team_hit,team_hit_reported,team_hit_reported_user_kicked,user_created,user_deleted,user_renamed,user_rewarded") + .Annotation("Npgsql:Enum:battle_fighter_application_status", "accepted,declined,intent,pending") + .Annotation("Npgsql:Enum:battle_mercenary_application_status", "accepted,declined,pending") + .Annotation("Npgsql:Enum:battle_participant_type", "clan_member,mercenary,party") + .Annotation("Npgsql:Enum:battle_phase", "end,hiring,live,preparation,scheduled") + .Annotation("Npgsql:Enum:battle_side", "attacker,defender") + .Annotation("Npgsql:Enum:character_class", "archer,cavalry,crossbowman,infantry,mounted_archer,peasant,shock_infantry,skirmisher") + .Annotation("Npgsql:Enum:clan_invitation_status", "accepted,declined,pending") + .Annotation("Npgsql:Enum:clan_invitation_type", "offer,request") + .Annotation("Npgsql:Enum:clan_member_role", "leader,member,officer") + .Annotation("Npgsql:Enum:culture", "aserai,battania,empire,khuzait,looters,neutral,sturgia,vlandia") + .Annotation("Npgsql:Enum:damage_type", "blunt,cut,pierce,undefined") + .Annotation("Npgsql:Enum:game_mode", "crpg_battle,crpg_captain,crpg_conquest,crpg_duel,crpg_siege,crpg_skirmish,crpg_team_deathmatch,crpg_unknown_game_mode,crpgdtv") + .Annotation("Npgsql:Enum:item_slot", "body,hand,head,leg,mount,mount_harness,shoulder,weapon0,weapon1,weapon2,weapon3,weapon_extra") + .Annotation("Npgsql:Enum:item_type", "arrows,banner,body_armor,bolts,bow,bullets,crossbow,hand_armor,head_armor,leg_armor,mount,mount_harness,musket,one_handed_weapon,pistol,polearm,shield,shoulder_armor,thrown,two_handed_weapon,undefined") + .Annotation("Npgsql:Enum:languages", "be,bg,cs,da,de,el,en,es,fi,fr,hr,hu,it,lv,nl,no,pl,pt,ro,ru,sr,sv,tr,uk,zh") + .Annotation("Npgsql:Enum:marketplace_listing_asset_side", "offered,requested") + .Annotation("Npgsql:Enum:notification_state", "read,unread") + .Annotation("Npgsql:Enum:notification_type", "battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked_to_ex_participant,character_rewarded_to_user,clan_application_accepted_to_user,clan_application_created_to_officers,clan_application_created_to_user,clan_application_declined_to_user,clan_armory_borrow_item_to_lender,clan_armory_remove_item_to_borrower,clan_member_kicked_to_ex_member,clan_member_leaved_to_leader,clan_member_role_changed_to_user,item_returned,marketplace_listing_accepted_to_buyer,marketplace_listing_accepted_to_seller,marketplace_listing_expired,marketplace_listing_invalidated,user_rewarded_to_user") + .Annotation("Npgsql:Enum:party_order_type", "attack_party,attack_settlement,follow_party,join_battle,move_to_point,move_to_settlement,transfer_offer_party") + .Annotation("Npgsql:Enum:party_status", "awaiting_battle_join_decision,awaiting_party_offer_decision,idle,idle_in_settlement,in_battle,recruiting_in_settlement") + .Annotation("Npgsql:Enum:party_transfer_offer_status", "intent,pending") + .Annotation("Npgsql:Enum:platform", "epic_games,microsoft,steam") + .Annotation("Npgsql:Enum:quest_aggregation_type", "count,sum") + .Annotation("Npgsql:Enum:quest_type", "daily,weekly") + .Annotation("Npgsql:Enum:region", "as,eu,na,oc") + .Annotation("Npgsql:Enum:restriction_type", "all,chat,join") + .Annotation("Npgsql:Enum:role", "admin,game_admin,moderator,user") + .Annotation("Npgsql:Enum:settlement_type", "castle,town,village") + .Annotation("Npgsql:Enum:terrain_type", "barrier,deep_water,plain,shallow_water,sparse_forest,thick_forest") + .Annotation("Npgsql:Enum:weapon_class", "arrow,banner,bolt,boulder,bow,cartridge,crossbow,dagger,javelin,large_shield,low_grip_polearm,mace,musket,one_handed_axe,one_handed_polearm,one_handed_sword,pick,pistol,small_shield,stone,throwing_axe,throwing_knife,two_handed_axe,two_handed_mace,two_handed_polearm,two_handed_sword,undefined") + .Annotation("Npgsql:PostgresExtension:postgis", ",,") + .OldAnnotation("Npgsql:Enum:activity_log_type", "battle_apply_as_mercenary,battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked,battle_participant_leaved,character_created,character_deleted,character_earned,character_rating_reset,character_respecialized,character_retired,character_rewarded,chat_message_sent,clan_application_accepted,clan_application_created,clan_application_declined,clan_armory_add_item,clan_armory_borrow_item,clan_armory_remove_item,clan_armory_return_item,clan_created,clan_deleted,clan_member_kicked,clan_member_leaved,clan_member_role_edited,item_bought,item_broke,item_reforged,item_repaired,item_returned,item_sold,item_upgraded,marketplace_listing_accepted,marketplace_listing_cancelled,marketplace_listing_created,marketplace_listing_expired,marketplace_listing_invalidated,quest_rerolled,quest_reward_claimed,server_joined,team_hit,team_hit_reported,team_hit_reported_user_kicked,user_created,user_deleted,user_renamed,user_rewarded") + .OldAnnotation("Npgsql:Enum:battle_fighter_application_status", "accepted,declined,intent,pending") + .OldAnnotation("Npgsql:Enum:battle_mercenary_application_status", "accepted,declined,pending") + .OldAnnotation("Npgsql:Enum:battle_participant_type", "clan_member,mercenary,party") + .OldAnnotation("Npgsql:Enum:battle_phase", "end,hiring,live,preparation,scheduled") + .OldAnnotation("Npgsql:Enum:battle_side", "attacker,defender") + .OldAnnotation("Npgsql:Enum:character_class", "archer,cavalry,crossbowman,infantry,mounted_archer,peasant,shock_infantry,skirmisher") + .OldAnnotation("Npgsql:Enum:clan_invitation_status", "accepted,declined,pending") + .OldAnnotation("Npgsql:Enum:clan_invitation_type", "offer,request") + .OldAnnotation("Npgsql:Enum:clan_member_role", "leader,member,officer") + .OldAnnotation("Npgsql:Enum:culture", "aserai,battania,empire,khuzait,looters,neutral,sturgia,vlandia") + .OldAnnotation("Npgsql:Enum:damage_type", "blunt,cut,pierce,undefined") + .OldAnnotation("Npgsql:Enum:game_mode", "crpg_battle,crpg_captain,crpg_conquest,crpg_duel,crpg_siege,crpg_skirmish,crpg_team_deathmatch,crpg_unknown_game_mode,crpgdtv") + .OldAnnotation("Npgsql:Enum:item_slot", "body,hand,head,leg,mount,mount_harness,shoulder,weapon0,weapon1,weapon2,weapon3,weapon_extra") + .OldAnnotation("Npgsql:Enum:item_type", "arrows,banner,body_armor,bolts,bow,bullets,crossbow,hand_armor,head_armor,leg_armor,mount,mount_harness,musket,one_handed_weapon,pistol,polearm,shield,shoulder_armor,thrown,two_handed_weapon,undefined") + .OldAnnotation("Npgsql:Enum:languages", "be,bg,cs,da,de,el,en,es,fi,fr,hr,hu,it,lv,nl,no,pl,pt,ro,ru,sr,sv,tr,uk,zh") + .OldAnnotation("Npgsql:Enum:marketplace_listing_asset_side", "offered,requested") + .OldAnnotation("Npgsql:Enum:notification_state", "read,unread") + .OldAnnotation("Npgsql:Enum:notification_type", "battle_mercenary_application_accepted,battle_mercenary_application_declined,battle_participant_kicked_to_ex_participant,character_rewarded_to_user,clan_application_accepted_to_user,clan_application_created_to_officers,clan_application_created_to_user,clan_application_declined_to_user,clan_armory_borrow_item_to_lender,clan_armory_remove_item_to_borrower,clan_member_kicked_to_ex_member,clan_member_leaved_to_leader,clan_member_role_changed_to_user,item_returned,marketplace_listing_accepted_to_buyer,marketplace_listing_accepted_to_seller,marketplace_listing_expired,marketplace_listing_invalidated,user_rewarded_to_user") + .OldAnnotation("Npgsql:Enum:party_order_type", "attack_party,attack_settlement,follow_party,join_battle,move_to_point,move_to_settlement,transfer_offer_party") + .OldAnnotation("Npgsql:Enum:party_status", "awaiting_battle_join_decision,awaiting_party_offer_decision,idle,idle_in_settlement,in_battle,recruiting_in_settlement") + .OldAnnotation("Npgsql:Enum:party_transfer_offer_status", "intent,pending") + .OldAnnotation("Npgsql:Enum:platform", "epic_games,microsoft,steam") + .OldAnnotation("Npgsql:Enum:quest_aggregation_type", "count,sum") + .OldAnnotation("Npgsql:Enum:quest_type", "daily,weekly") + .OldAnnotation("Npgsql:Enum:region", "as,eu,na,oc") + .OldAnnotation("Npgsql:Enum:restriction_type", "all,chat,join") + .OldAnnotation("Npgsql:Enum:role", "admin,game_admin,moderator,user") + .OldAnnotation("Npgsql:Enum:settlement_type", "castle,town,village") + .OldAnnotation("Npgsql:Enum:terrain_type", "barrier,deep_water,plain,shallow_water,sparse_forest,thick_forest") + .OldAnnotation("Npgsql:Enum:theme_equipment_slot", "body,hand,head,leg,mount,mount_harness,shoulder,weapon0,weapon1,weapon2,weapon3,weapon_extra") + .OldAnnotation("Npgsql:Enum:weapon_class", "arrow,banner,bolt,boulder,bow,cartridge,crossbow,dagger,javelin,large_shield,low_grip_polearm,mace,musket,one_handed_axe,one_handed_polearm,one_handed_sword,pick,pistol,small_shield,stone,throwing_axe,throwing_knife,two_handed_axe,two_handed_mace,two_handed_polearm,two_handed_sword,undefined") + .OldAnnotation("Npgsql:PostgresExtension:postgis", ",,"); + } + } +} diff --git a/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs b/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs index b3ea740f0..235251791 100644 --- a/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs +++ b/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs @@ -1,3203 +1,3314 @@ -// -using System; -using Crpg.Domain.Entities; -using Crpg.Domain.Entities.ActivityLogs; -using Crpg.Domain.Entities.Battles; -using Crpg.Domain.Entities.Characters; -using Crpg.Domain.Entities.Clans; -using Crpg.Domain.Entities.Items; -using Crpg.Domain.Entities.Marketplace; -using Crpg.Domain.Entities.Notifications; -using Crpg.Domain.Entities.Parties; -using Crpg.Domain.Entities.Quests; -using Crpg.Domain.Entities.Restrictions; -using Crpg.Domain.Entities.Servers; -using Crpg.Domain.Entities.Settlements; -using Crpg.Domain.Entities.Terrains; -using Crpg.Domain.Entities.Users; -using Crpg.Persistence; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using NetTopologySuite.Geometries; -using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; - -#nullable disable - -namespace Crpg.Persistence.Migrations -{ - [DbContext(typeof(CrpgDbContext))] - partial class CrpgDbContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "10.0.7") - .HasAnnotation("Relational:MaxIdentifierLength", 63); - - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "activity_log_type", new[] { "battle_apply_as_mercenary", "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked", "battle_participant_leaved", "character_created", "character_deleted", "character_earned", "character_rating_reset", "character_respecialized", "character_retired", "character_rewarded", "chat_message_sent", "clan_application_accepted", "clan_application_created", "clan_application_declined", "clan_armory_add_item", "clan_armory_borrow_item", "clan_armory_remove_item", "clan_armory_return_item", "clan_created", "clan_deleted", "clan_member_kicked", "clan_member_leaved", "clan_member_role_edited", "item_bought", "item_broke", "item_reforged", "item_repaired", "item_returned", "item_sold", "item_upgraded", "marketplace_listing_accepted", "marketplace_listing_cancelled", "marketplace_listing_created", "marketplace_listing_expired", "marketplace_listing_invalidated", "quest_rerolled", "quest_reward_claimed", "server_joined", "team_hit", "team_hit_reported", "team_hit_reported_user_kicked", "user_created", "user_deleted", "user_renamed", "user_rewarded" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_fighter_application_status", new[] { "accepted", "declined", "intent", "pending" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_mercenary_application_status", new[] { "accepted", "declined", "pending" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_participant_type", new[] { "clan_member", "mercenary", "party" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_phase", new[] { "end", "hiring", "live", "preparation", "scheduled" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_side", new[] { "attacker", "defender" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_class", new[] { "archer", "cavalry", "crossbowman", "infantry", "mounted_archer", "peasant", "shock_infantry", "skirmisher" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_status", new[] { "accepted", "declined", "pending" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_type", new[] { "offer", "request" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_member_role", new[] { "leader", "member", "officer" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "culture", new[] { "aserai", "battania", "empire", "khuzait", "looters", "neutral", "sturgia", "vlandia" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "damage_type", new[] { "blunt", "cut", "pierce", "undefined" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "game_mode", new[] { "crpg_battle", "crpg_captain", "crpg_conquest", "crpg_duel", "crpg_siege", "crpg_skirmish", "crpg_team_deathmatch", "crpg_unknown_game_mode", "crpgdtv" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_type", new[] { "arrows", "banner", "body_armor", "bolts", "bow", "bullets", "crossbow", "hand_armor", "head_armor", "leg_armor", "mount", "mount_harness", "musket", "one_handed_weapon", "pistol", "polearm", "shield", "shoulder_armor", "thrown", "two_handed_weapon", "undefined" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "languages", new[] { "be", "bg", "cs", "da", "de", "el", "en", "es", "fi", "fr", "hr", "hu", "it", "lv", "nl", "no", "pl", "pt", "ro", "ru", "sr", "sv", "tr", "uk", "zh" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "marketplace_listing_asset_side", new[] { "offered", "requested" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_state", new[] { "read", "unread" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_type", new[] { "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked_to_ex_participant", "character_rewarded_to_user", "clan_application_accepted_to_user", "clan_application_created_to_officers", "clan_application_created_to_user", "clan_application_declined_to_user", "clan_armory_borrow_item_to_lender", "clan_armory_remove_item_to_borrower", "clan_member_kicked_to_ex_member", "clan_member_leaved_to_leader", "clan_member_role_changed_to_user", "item_returned", "marketplace_listing_accepted_to_buyer", "marketplace_listing_accepted_to_seller", "marketplace_listing_expired", "marketplace_listing_invalidated", "user_rewarded_to_user" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_order_type", new[] { "attack_party", "attack_settlement", "follow_party", "join_battle", "move_to_point", "move_to_settlement", "transfer_offer_party" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_status", new[] { "awaiting_battle_join_decision", "awaiting_party_offer_decision", "idle", "idle_in_settlement", "in_battle", "recruiting_in_settlement" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_transfer_offer_status", new[] { "intent", "pending" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "platform", new[] { "epic_games", "microsoft", "steam" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_aggregation_type", new[] { "count", "sum" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_type", new[] { "daily", "weekly" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "region", new[] { "as", "eu", "na", "oc" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "restriction_type", new[] { "all", "chat", "join" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "role", new[] { "admin", "game_admin", "moderator", "user" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "settlement_type", new[] { "castle", "town", "village" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "terrain_type", new[] { "barrier", "deep_water", "plain", "shallow_water", "sparse_forest", "thick_forest" }); - NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "weapon_class", new[] { "arrow", "banner", "bolt", "boulder", "bow", "cartridge", "crossbow", "dagger", "javelin", "large_shield", "low_grip_polearm", "mace", "musket", "one_handed_axe", "one_handed_polearm", "one_handed_sword", "pick", "pistol", "small_shield", "stone", "throwing_axe", "throwing_knife", "two_handed_axe", "two_handed_mace", "two_handed_polearm", "two_handed_sword", "undefined" }); - NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); - NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); - - modelBuilder.Entity("BattleParticipantStatistic", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Assists") - .HasColumnType("integer") - .HasColumnName("assists"); - - b.Property("BattleId") - .HasColumnType("integer") - .HasColumnName("battle_id"); - - b.Property("Deaths") - .HasColumnType("integer") - .HasColumnName("deaths"); - - b.Property("Kills") - .HasColumnType("integer") - .HasColumnName("kills"); - - b.Property("ParticipantId") - .HasColumnType("integer") - .HasColumnName("participant_id"); - - b.Property("Participated") - .HasColumnType("boolean") - .HasColumnName("participated"); - - b.HasKey("Id") - .HasName("pk_battle_participant_statistic"); - - b.HasIndex("BattleId") - .HasDatabaseName("ix_battle_participant_statistic_battle_id"); - - b.HasIndex("ParticipantId") - .IsUnique() - .HasDatabaseName("ix_battle_participant_statistic_participant_id"); - - b.ToTable("battle_participant_statistic", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Type") - .HasColumnType("activity_log_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_activity_logs"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_activity_logs_user_id"); - - b.HasIndex("CreatedAt", "UserId") - .HasDatabaseName("ix_activity_logs_created_at_user_id"); - - b.ToTable("activity_logs", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => - { - b.Property("ActivityLogId") - .HasColumnType("integer") - .HasColumnName("activity_log_id"); - - b.Property("Key") - .HasColumnType("text") - .HasColumnName("key"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasColumnName("value"); - - b.HasKey("ActivityLogId", "Key") - .HasName("pk_activity_log_metadata"); - - b.ToTable("activity_log_metadata", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Phase") - .HasColumnType("battle_phase") - .HasColumnName("phase"); - - b.Property("Position") - .IsRequired() - .HasColumnType("geometry") - .HasColumnName("position"); - - b.Property("Region") - .HasColumnType("region") - .HasColumnName("region"); - - b.Property("ScheduledFor") - .HasColumnType("timestamp with time zone") - .HasColumnName("scheduled_for"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_battles"); - - b.ToTable("battles", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BattleId") - .HasColumnType("integer") - .HasColumnName("battle_id"); - - b.Property("Commander") - .HasColumnType("boolean") - .HasColumnName("commander"); - - b.Property("ParticipantSlots") - .HasColumnType("integer") - .HasColumnName("participant_slots"); - - b.Property("PartyId") - .HasColumnType("integer") - .HasColumnName("party_id"); - - b.Property("SettlementId") - .HasColumnType("integer") - .HasColumnName("settlement_id"); - - b.Property("Side") - .HasColumnType("battle_side") - .HasColumnName("side"); - - b.HasKey("Id") - .HasName("pk_battle_fighters"); - - b.HasIndex("BattleId") - .HasDatabaseName("ix_battle_fighters_battle_id"); - - b.HasIndex("PartyId") - .HasDatabaseName("ix_battle_fighters_party_id"); - - b.HasIndex("SettlementId") - .HasDatabaseName("ix_battle_fighters_settlement_id"); - - b.ToTable("battle_fighters", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BattleId") - .HasColumnType("integer") - .HasColumnName("battle_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("PartyId") - .HasColumnType("integer") - .HasColumnName("party_id"); - - b.Property("Side") - .HasColumnType("battle_side") - .HasColumnName("side"); - - b.Property("Status") - .HasColumnType("battle_fighter_application_status") - .HasColumnName("status"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_battle_fighter_applications"); - - b.HasIndex("BattleId") - .HasDatabaseName("ix_battle_fighter_applications_battle_id"); - - b.HasIndex("PartyId") - .HasDatabaseName("ix_battle_fighter_applications_party_id"); - - b.ToTable("battle_fighter_applications", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BattleId") - .HasColumnType("integer") - .HasColumnName("battle_id"); - - b.Property("CharacterId") - .HasColumnType("integer") - .HasColumnName("character_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Note") - .IsRequired() - .HasColumnType("text") - .HasColumnName("note"); - - b.Property("Side") - .HasColumnType("battle_side") - .HasColumnName("side"); - - b.Property("Status") - .HasColumnType("battle_mercenary_application_status") - .HasColumnName("status"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Wage") - .HasColumnType("integer") - .HasColumnName("wage"); - - b.HasKey("Id") - .HasName("pk_battle_mercenary_applications"); - - b.HasIndex("BattleId") - .HasDatabaseName("ix_battle_mercenary_applications_battle_id"); - - b.HasIndex("CharacterId") - .HasDatabaseName("ix_battle_mercenary_applications_character_id"); - - b.ToTable("battle_mercenary_applications", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BattleId") - .HasColumnType("integer") - .HasColumnName("battle_id"); - - b.Property("CaptainFighterId") - .HasColumnType("integer") - .HasColumnName("captain_fighter_id"); - - b.Property("CharacterId") - .HasColumnType("integer") - .HasColumnName("character_id"); - - b.Property("MercenaryApplicationId") - .HasColumnType("integer") - .HasColumnName("mercenary_application_id"); - - b.Property("Side") - .HasColumnType("battle_side") - .HasColumnName("side"); - - b.Property("Type") - .HasColumnType("battle_participant_type") - .HasColumnName("type"); - - b.HasKey("Id") - .HasName("pk_battle_participants"); - - b.HasIndex("BattleId") - .HasDatabaseName("ix_battle_participants_battle_id"); - - b.HasIndex("CaptainFighterId") - .HasDatabaseName("ix_battle_participants_captain_fighter_id"); - - b.HasIndex("CharacterId") - .HasDatabaseName("ix_battle_participants_character_id"); - - b.HasIndex("MercenaryApplicationId") - .HasDatabaseName("ix_battle_participants_mercenary_application_id"); - - b.ToTable("battle_participants", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("BattleId") - .HasColumnType("integer") - .HasColumnName("battle_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Note") - .IsRequired() - .HasColumnType("text") - .HasColumnName("note"); - - b.Property("Side") - .HasColumnType("battle_side") - .HasColumnName("side"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_battle_side_briefings"); - - b.HasIndex("BattleId", "Side") - .IsUnique() - .HasDatabaseName("ix_battle_side_briefings_battle_id_side"); - - b.ToTable("battle_side_briefings", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Class") - .HasColumnType("character_class") - .HasColumnName("class"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("deleted_at"); - - b.Property("Experience") - .HasColumnType("integer") - .HasColumnName("experience"); - - b.Property("ForTournament") - .HasColumnType("boolean") - .HasColumnName("for_tournament"); - - b.Property("Generation") - .HasColumnType("integer") - .HasColumnName("generation"); - - b.Property("Level") - .HasColumnType("integer") - .HasColumnName("level"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("xid") - .HasColumnName("xmin"); - - b.HasKey("Id") - .HasName("pk_characters"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_characters_user_id"); - - b.ToTable("characters", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ArmoryTimeout") - .HasColumnType("interval") - .HasColumnName("armory_timeout"); - - b.Property("BannerKey") - .IsRequired() - .HasColumnType("text") - .HasColumnName("banner_key"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Description") - .IsRequired() - .HasColumnType("text") - .HasColumnName("description"); - - b.Property("Discord") - .HasColumnType("text") - .HasColumnName("discord"); - - b.PrimitiveCollection("Languages") - .IsRequired() - .HasColumnType("languages[]") - .HasColumnName("languages"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("PrimaryColor") - .HasColumnType("bigint") - .HasColumnName("primary_color"); - - b.Property("Region") - .HasColumnType("region") - .HasColumnName("region"); - - b.Property("SecondaryColor") - .HasColumnType("bigint") - .HasColumnName("secondary_color"); - - b.Property("Tag") - .IsRequired() - .HasColumnType("text") - .HasColumnName("tag"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_clans"); - - b.HasIndex("Name") - .IsUnique() - .HasDatabaseName("ix_clans_name"); - - b.HasIndex("Tag") - .IsUnique() - .HasDatabaseName("ix_clans_tag"); - - b.ToTable("clans", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => - { - b.Property("UserItemId") - .HasColumnType("integer") - .HasColumnName("user_item_id"); - - b.Property("BorrowerClanId") - .HasColumnType("integer") - .HasColumnName("borrower_clan_id"); - - b.Property("BorrowerUserId") - .HasColumnType("integer") - .HasColumnName("borrower_user_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("UserItemId") - .HasName("pk_clan_armory_borrowed_items"); - - b.HasIndex("BorrowerClanId") - .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_clan_id"); - - b.HasIndex("BorrowerUserId") - .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_user_id"); - - b.ToTable("clan_armory_borrowed_items", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ClanId") - .HasColumnType("integer") - .HasColumnName("clan_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("InviteeId") - .HasColumnType("integer") - .HasColumnName("invitee_id"); - - b.Property("InviterId") - .HasColumnType("integer") - .HasColumnName("inviter_id"); - - b.Property("Status") - .HasColumnType("clan_invitation_status") - .HasColumnName("status"); - - b.Property("Type") - .HasColumnType("clan_invitation_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_clan_invitations"); - - b.HasIndex("ClanId") - .HasDatabaseName("ix_clan_invitations_clan_id"); - - b.HasIndex("InviteeId") - .HasDatabaseName("ix_clan_invitations_invitee_id"); - - b.HasIndex("InviterId") - .HasDatabaseName("ix_clan_invitations_inviter_id"); - - b.ToTable("clan_invitations", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => - { - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.Property("ClanId") - .HasColumnType("integer") - .HasColumnName("clan_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Role") - .HasColumnType("clan_member_role") - .HasColumnName("role"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("UserId") - .HasName("pk_clan_members"); - - b.HasIndex("ClanId") - .HasDatabaseName("ix_clan_members_clan_id"); - - b.ToTable("clan_members", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("EventData") - .HasColumnType("jsonb") - .HasColumnName("event_data"); - - b.Property("GameMode") - .HasColumnType("game_mode") - .HasColumnName("game_mode"); - - b.Property("Instance") - .IsRequired() - .HasColumnType("text") - .HasColumnName("instance"); - - b.Property("Type") - .HasColumnType("integer") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_game_events"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("ix_game_events_created_at"); - - b.HasIndex("UserId", "Type", "CreatedAt") - .HasDatabaseName("ix_game_events_user_id_type_created_at"); - - b.ToTable("game_events", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => - { - b.Property("UserItemId") - .HasColumnType("integer") - .HasColumnName("user_item_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("LenderClanId") - .HasColumnType("integer") - .HasColumnName("lender_clan_id"); - - b.Property("LenderUserId") - .HasColumnType("integer") - .HasColumnName("lender_user_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("UserItemId") - .HasName("pk_clan_armory_items"); - - b.HasIndex("LenderClanId") - .HasDatabaseName("ix_clan_armory_items_lender_clan_id"); - - b.HasIndex("LenderUserId") - .HasDatabaseName("ix_clan_armory_items_lender_user_id"); - - b.ToTable("clan_armory_items", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => - { - b.Property("CharacterId") - .HasColumnType("integer") - .HasColumnName("character_id"); - - b.Property("Slot") - .HasColumnType("item_slot") - .HasColumnName("slot"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserItemId") - .HasColumnType("integer") - .HasColumnName("user_item_id"); - - b.HasKey("CharacterId", "Slot") - .HasName("pk_equipped_items"); - - b.HasIndex("UserItemId") - .HasDatabaseName("ix_equipped_items_user_item_id"); - - b.ToTable("equipped_items", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => - { - b.Property("Id") - .HasColumnType("text") - .HasColumnName("id"); - - b.Property("BaseId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("base_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Culture") - .HasColumnType("culture") - .HasColumnName("culture"); - - b.Property("Enabled") - .HasColumnType("boolean") - .HasColumnName("enabled"); - - b.Property("Flags") - .HasColumnType("integer") - .HasColumnName("flags"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("Price") - .HasColumnType("integer") - .HasColumnName("price"); - - b.Property("Rank") - .HasColumnType("integer") - .HasColumnName("rank"); - - b.Property("Requirement") - .HasColumnType("integer") - .HasColumnName("requirement"); - - b.Property("Tier") - .HasColumnType("real") - .HasColumnName("tier"); - - b.Property("Type") - .HasColumnType("item_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Weight") - .HasColumnType("real") - .HasColumnName("weight"); - - b.HasKey("Id") - .HasName("pk_items"); - - b.ToTable("items", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Count") - .HasColumnType("integer") - .HasColumnName("count"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("ItemId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("item_id"); - - b.Property("PartyId") - .HasColumnType("integer") - .HasColumnName("party_id"); - - b.Property("PartyTransferOfferId") - .HasColumnType("integer") - .HasColumnName("party_transfer_offer_id"); - - b.Property("SettlementId") - .HasColumnType("integer") - .HasColumnName("settlement_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_item_stacks"); - - b.HasIndex("ItemId") - .HasDatabaseName("ix_item_stacks_item_id"); - - b.HasIndex("PartyId", "ItemId") - .IsUnique() - .HasDatabaseName("ix_item_stacks_party_id_item_id") - .HasFilter("party_id IS NOT NULL"); - - b.HasIndex("PartyTransferOfferId", "ItemId") - .IsUnique() - .HasDatabaseName("ix_item_stacks_party_transfer_offer_id_item_id") - .HasFilter("party_transfer_offer_id IS NOT NULL"); - - b.HasIndex("SettlementId", "ItemId") - .IsUnique() - .HasDatabaseName("ix_item_stacks_settlement_id_item_id") - .HasFilter("settlement_id IS NOT NULL"); - - b.ToTable("item_stacks", null, t => - { - t.HasCheckConstraint("CK_item_stacks_single_owner", "(party_id IS NOT NULL)::int + (settlement_id IS NOT NULL)::int + (party_transfer_offer_id IS NOT NULL)::int = 1"); - }); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => - { - b.Property("UserItemId") - .HasColumnType("integer") - .HasColumnName("user_item_id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("UserItemId") - .HasName("pk_personal_items"); - - b.ToTable("personal_items", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("IsBroken") - .HasColumnType("boolean") - .HasColumnName("is_broken"); - - b.Property("ItemId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("item_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_user_items"); - - b.HasIndex("ItemId") - .HasDatabaseName("ix_user_items_item_id"); - - b.HasIndex("UserId", "ItemId") - .HasDatabaseName("ix_user_items_user_id_item_id"); - - b.ToTable("user_items", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(300) - .HasColumnType("character varying(300)") - .HasColumnName("name"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_user_item_presets"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_user_item_presets_user_id"); - - b.ToTable("user_item_presets", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => - { - b.Property("UserItemPresetId") - .HasColumnType("integer") - .HasColumnName("user_item_preset_id"); - - b.Property("Slot") - .HasColumnType("item_slot") - .HasColumnName("slot"); - - b.Property("ItemId") - .HasColumnType("text") - .HasColumnName("item_id"); - - b.HasKey("UserItemPresetId", "Slot") - .HasName("pk_user_item_preset_slots"); - - b.HasIndex("ItemId") - .HasDatabaseName("ix_user_item_preset_slots_item_id"); - - b.ToTable("user_item_preset_slots", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => - { - b.Property("CharacterId") - .HasColumnType("integer") - .HasColumnName("character_id"); - - b.Property("LastRespecializeAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("last_respecialize_at"); - - b.HasKey("CharacterId") - .HasName("pk_character_limitations"); - - b.ToTable("character_limitations", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("expires_at"); - - b.Property("GoldFee") - .HasColumnType("integer") - .HasColumnName("gold_fee"); - - b.Property("SellerId") - .HasColumnType("integer") - .HasColumnName("seller_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("xid") - .HasColumnName("xmin"); - - b.HasKey("Id") - .HasName("pk_marketplace_listings"); - - b.HasIndex("CreatedAt") - .HasDatabaseName("ix_marketplace_listings_created_at"); - - b.HasIndex("ExpiresAt") - .HasDatabaseName("ix_marketplace_listings_expires_at"); - - b.HasIndex("SellerId", "CreatedAt") - .HasDatabaseName("ix_marketplace_listings_seller_id_created_at"); - - b.ToTable("marketplace_listings", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Gold") - .HasColumnType("integer") - .HasColumnName("gold"); - - b.Property("HeirloomPoints") - .HasColumnType("integer") - .HasColumnName("heirloom_points"); - - b.Property("ItemId") - .HasColumnType("text") - .HasColumnName("item_id"); - - b.Property("MarketplaceListingId") - .HasColumnType("integer") - .HasColumnName("marketplace_listing_id"); - - b.Property("Side") - .HasColumnType("marketplace_listing_asset_side") - .HasColumnName("side"); - - b.Property("UserItemId") - .HasColumnType("integer") - .HasColumnName("user_item_id"); - - b.HasKey("Id") - .HasName("pk_marketplace_listing_assets"); - - b.HasIndex("ItemId") - .HasDatabaseName("ix_marketplace_listing_assets_item_id"); - - b.HasIndex("UserItemId") - .HasDatabaseName("ix_marketplace_listing_assets_user_item_id"); - - b.HasIndex("MarketplaceListingId", "Side") - .HasDatabaseName("ix_marketplace_listing_assets_marketplace_listing_id_side"); - - b.ToTable("marketplace_listing_assets", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("State") - .HasColumnType("notification_state") - .HasColumnName("state"); - - b.Property("Type") - .HasColumnType("notification_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.HasKey("Id") - .HasName("pk_user_notifications"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_user_notifications_user_id"); - - b.ToTable("user_notifications", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => - { - b.Property("UserNotificationId") - .HasColumnType("integer") - .HasColumnName("user_notification_id"); - - b.Property("Key") - .HasColumnType("text") - .HasColumnName("key"); - - b.Property("Value") - .IsRequired() - .HasColumnType("text") - .HasColumnName("value"); - - b.HasKey("UserNotificationId", "Key") - .HasName("pk_user_notification_metadata"); - - b.ToTable("user_notification_metadata", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => - { - b.Property("Id") - .HasColumnType("integer") - .HasColumnName("id"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("CurrentBattleId") - .HasColumnType("integer") - .HasColumnName("current_battle_id"); - - b.Property("CurrentPartyId") - .HasColumnType("integer") - .HasColumnName("current_party_id"); - - b.Property("CurrentSettlementId") - .HasColumnType("integer") - .HasColumnName("current_settlement_id"); - - b.Property("Gold") - .HasColumnType("integer") - .HasColumnName("gold"); - - b.Property("Position") - .IsRequired() - .HasColumnType("geometry") - .HasColumnName("position"); - - b.Property("Status") - .HasColumnType("party_status") - .HasColumnName("status"); - - b.Property("Troops") - .HasColumnType("real") - .HasColumnName("troops"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_parties"); - - b.HasIndex("CurrentBattleId") - .HasDatabaseName("ix_parties_current_battle_id"); - - b.HasIndex("CurrentPartyId") - .HasDatabaseName("ix_parties_current_party_id"); - - b.HasIndex("CurrentSettlementId") - .HasDatabaseName("ix_parties_current_settlement_id"); - - b.ToTable("parties", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("OrderIndex") - .HasColumnType("integer") - .HasColumnName("order_index"); - - b.Property("PartyId") - .HasColumnType("integer") - .HasColumnName("party_id"); - - b.Property("TargetedBattleId") - .HasColumnType("integer") - .HasColumnName("targeted_battle_id"); - - b.Property("TargetedPartyId") - .HasColumnType("integer") - .HasColumnName("targeted_party_id"); - - b.Property("TargetedSettlementId") - .HasColumnType("integer") - .HasColumnName("targeted_settlement_id"); - - b.Property("Type") - .HasColumnType("party_order_type") - .HasColumnName("type"); - - b.Property("Waypoints") - .IsRequired() - .HasColumnType("geometry") - .HasColumnName("waypoints"); - - b.HasKey("Id") - .HasName("pk_party_orders"); - - b.HasIndex("PartyId") - .HasDatabaseName("ix_party_orders_party_id"); - - b.HasIndex("TargetedBattleId") - .HasDatabaseName("ix_party_orders_targeted_battle_id"); - - b.HasIndex("TargetedPartyId") - .HasDatabaseName("ix_party_orders_targeted_party_id"); - - b.HasIndex("TargetedSettlementId") - .HasDatabaseName("ix_party_orders_targeted_settlement_id"); - - b.ToTable("party_orders", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Gold") - .HasColumnType("integer") - .HasColumnName("gold"); - - b.Property("PartyId") - .HasColumnType("integer") - .HasColumnName("party_id"); - - b.Property("Status") - .HasColumnType("party_transfer_offer_status") - .HasColumnName("status"); - - b.Property("TargetPartyId") - .HasColumnType("integer") - .HasColumnName("target_party_id"); - - b.Property("Troops") - .HasColumnType("real") - .HasColumnName("troops"); - - b.HasKey("Id") - .HasName("pk_party_transfer_offers"); - - b.HasIndex("PartyId") - .HasDatabaseName("ix_party_transfer_offers_party_id"); - - b.HasIndex("TargetPartyId") - .HasDatabaseName("ix_party_transfer_offers_target_party_id"); - - b.ToTable("party_transfer_offers", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Quests.QuestDefinition", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("AggregationField") - .HasColumnType("integer") - .HasColumnName("aggregation_field"); - - b.Property("AggregationType") - .HasColumnType("quest_aggregation_type") - .HasColumnName("aggregation_type"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("EventFiltersJson") - .HasColumnType("jsonb") - .HasColumnName("event_filters_json"); - - b.Property("EventType") - .HasColumnType("integer") - .HasColumnName("event_type"); - - b.Property("IsActive") - .ValueGeneratedOnAdd() - .HasColumnType("boolean") - .HasDefaultValue(true) - .HasColumnName("is_active"); - - b.Property("RequiredValue") - .HasColumnType("integer") - .HasColumnName("required_value"); - - b.Property("RewardExperience") - .HasColumnType("integer") - .HasColumnName("reward_experience"); - - b.Property("RewardGold") - .HasColumnType("integer") - .HasColumnName("reward_gold"); - - b.Property("Type") - .HasColumnType("quest_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_quest_definitions"); - - b.ToTable("quest_definitions", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("expires_at"); - - b.Property("IsRewardClaimed") - .HasColumnType("boolean") - .HasColumnName("is_reward_claimed"); - - b.Property("QuestDefinitionId") - .HasColumnType("integer") - .HasColumnName("quest_definition_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("UserId") - .HasColumnType("integer") - .HasColumnName("user_id"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("xid") - .HasColumnName("xmin"); - - b.HasKey("Id") - .HasName("pk_user_quests"); - - b.HasIndex("QuestDefinitionId") - .HasDatabaseName("ix_user_quests_quest_definition_id"); - - b.HasIndex("UserId") - .HasDatabaseName("ix_user_quests_user_id"); - - b.ToTable("user_quests", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("ExpiresAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("expires_at"); - - b.Property("QuestDefinitionId") - .HasColumnType("integer") - .HasColumnName("quest_definition_id"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_weekly_quest_assignments"); - - b.HasIndex("ExpiresAt") - .HasDatabaseName("ix_weekly_quest_assignments_expires_at"); - - b.HasIndex("QuestDefinitionId") - .HasDatabaseName("ix_weekly_quest_assignments_quest_definition_id"); - - b.ToTable("weekly_quest_assignments", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Duration") - .HasColumnType("interval") - .HasColumnName("duration"); - - b.Property("PublicReason") - .IsRequired() - .HasColumnType("text") - .HasColumnName("public_reason"); - - b.Property("Reason") - .IsRequired() - .HasColumnType("text") - .HasColumnName("reason"); - - b.Property("RestrictedByUserId") - .HasColumnType("integer") - .HasColumnName("restricted_by_user_id"); - - b.Property("RestrictedUserId") - .HasColumnType("integer") - .HasColumnName("restricted_user_id"); - - b.Property("Type") - .HasColumnType("restriction_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_restrictions"); - - b.HasIndex("RestrictedByUserId") - .HasDatabaseName("ix_restrictions_restricted_by_user_id"); - - b.HasIndex("RestrictedUserId") - .HasDatabaseName("ix_restrictions_restricted_user_id"); - - b.ToTable("restrictions", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Settings.Setting", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Discord") - .IsRequired() - .HasColumnType("text") - .HasColumnName("discord"); - - b.Property("Github") - .IsRequired() - .HasColumnType("text") - .HasColumnName("github"); - - b.Property("HappyHours") - .IsRequired() - .HasColumnType("text") - .HasColumnName("happy_hours"); - - b.Property("ModDb") - .IsRequired() - .HasColumnType("text") - .HasColumnName("mod_db"); - - b.Property("Patreon") - .IsRequired() - .HasColumnType("text") - .HasColumnName("patreon"); - - b.Property("Reddit") - .IsRequired() - .HasColumnType("text") - .HasColumnName("reddit"); - - b.Property("Steam") - .IsRequired() - .HasColumnType("text") - .HasColumnName("steam"); - - b.HasKey("Id") - .HasName("pk_settings"); - - b.ToTable("settings", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Culture") - .HasColumnType("culture") - .HasColumnName("culture"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("OwnerId") - .HasColumnType("integer") - .HasColumnName("owner_id"); - - b.Property("Position") - .IsRequired() - .HasColumnType("geometry") - .HasColumnName("position"); - - b.Property("Region") - .HasColumnType("region") - .HasColumnName("region"); - - b.Property("Scene") - .IsRequired() - .HasColumnType("text") - .HasColumnName("scene"); - - b.Property("Troops") - .HasColumnType("integer") - .HasColumnName("troops"); - - b.Property("Type") - .HasColumnType("settlement_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_settlements"); - - b.HasIndex("OwnerId") - .HasDatabaseName("ix_settlements_owner_id"); - - b.HasIndex("Region", "Name") - .IsUnique() - .HasDatabaseName("ix_settlements_region_name"); - - b.ToTable("settlements", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Terrains.Terrain", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("Boundary") - .IsRequired() - .HasColumnType("geometry") - .HasColumnName("boundary"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("Type") - .HasColumnType("terrain_type") - .HasColumnName("type"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.HasKey("Id") - .HasName("pk_terrains"); - - b.ToTable("terrains", (string)null); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("ActiveCharacterId") - .HasColumnType("integer") - .HasColumnName("active_character_id"); - - b.Property("Avatar") - .HasColumnType("text") - .HasColumnName("avatar"); - - b.Property("CreatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("created_at"); - - b.Property("DeletedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("deleted_at"); - - b.Property("ExperienceMultiplier") - .HasColumnType("real") - .HasColumnName("experience_multiplier"); - - b.Property("Gold") - .HasColumnType("integer") - .HasColumnName("gold"); - - b.Property("HeirloomPoints") - .HasColumnType("integer") - .HasColumnName("heirloom_points"); - - b.Property("IsDonor") - .HasColumnType("boolean") - .HasColumnName("is_donor"); - - b.Property("Name") - .IsRequired() - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("Note") - .IsRequired() - .HasColumnType("text") - .HasColumnName("note"); - - b.Property("Platform") - .HasColumnType("platform") - .HasColumnName("platform"); - - b.Property("PlatformUserId") - .IsRequired() - .HasColumnType("text") - .HasColumnName("platform_user_id"); - - b.Property("Region") - .HasColumnType("region") - .HasColumnName("region"); - - b.Property("Role") - .HasColumnType("role") - .HasColumnName("role"); - - b.Property("UpdatedAt") - .HasColumnType("timestamp with time zone") - .HasColumnName("updated_at"); - - b.Property("Version") - .IsConcurrencyToken() - .ValueGeneratedOnAddOrUpdate() - .HasColumnType("xid") - .HasColumnName("xmin"); - - b.HasKey("Id") - .HasName("pk_users"); - - b.HasIndex("ActiveCharacterId") - .IsUnique() - .HasDatabaseName("ix_users_active_character_id"); - - b.HasIndex("Platform", "PlatformUserId") - .IsUnique() - .HasDatabaseName("ix_users_platform_platform_user_id"); - - b.ToTable("users", (string)null); - }); - - modelBuilder.Entity("BattleParticipantStatistic", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") - .WithMany() - .HasForeignKey("BattleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_participant_statistic_battles_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Battles.BattleParticipant", "Participant") - .WithOne("Statistic") - .HasForeignKey("BattleParticipantStatistic", "ParticipantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_participant_statistic_battle_participants_participan"); - - b.Navigation("Battle"); - - b.Navigation("Participant"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_activity_logs_users_user_id"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => - { - b.HasOne("Crpg.Domain.Entities.ActivityLogs.ActivityLog", null) - .WithMany("Metadata") - .HasForeignKey("ActivityLogId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_activity_log_metadata_activity_logs_activity_log_id"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") - .WithMany("Fighters") - .HasForeignKey("BattleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_fighters_battles_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") - .WithMany() - .HasForeignKey("PartyId") - .HasConstraintName("fk_battle_fighters_parties_party_id"); - - b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") - .WithMany() - .HasForeignKey("SettlementId") - .HasConstraintName("fk_battle_fighters_settlements_settlement_id"); - - b.Navigation("Battle"); - - b.Navigation("Party"); - - b.Navigation("Settlement"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") - .WithMany("FighterApplications") - .HasForeignKey("BattleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_fighter_applications_battles_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") - .WithMany() - .HasForeignKey("PartyId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_fighter_applications_parties_party_id"); - - b.Navigation("Battle"); - - b.Navigation("Party"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") - .WithMany("MercenaryApplications") - .HasForeignKey("BattleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_mercenary_applications_battles_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") - .WithMany() - .HasForeignKey("CharacterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_mercenary_applications_characters_character_id"); - - b.Navigation("Battle"); - - b.Navigation("Character"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") - .WithMany("Participants") - .HasForeignKey("BattleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_participants_battles_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Battles.BattleFighter", "CaptainFighter") - .WithMany() - .HasForeignKey("CaptainFighterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_participants_battle_fighters_captain_fighter_id"); - - b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") - .WithMany() - .HasForeignKey("CharacterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_participants_characters_character_id"); - - b.HasOne("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", "MercenaryApplication") - .WithMany() - .HasForeignKey("MercenaryApplicationId") - .HasConstraintName("fk_battle_participants_battle_mercenary_applications_mercenary"); - - b.Navigation("Battle"); - - b.Navigation("CaptainFighter"); - - b.Navigation("Character"); - - b.Navigation("MercenaryApplication"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") - .WithMany("SideBriefings") - .HasForeignKey("BattleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_battle_side_briefings_battles_battle_id"); - - b.Navigation("Battle"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany("Characters") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_characters_users_user_id"); - - b.OwnsOne("Crpg.Domain.Entities.Characters.CharacterCharacteristics", "Characteristics", b1 => - { - b1.Property("CharacterId") - .HasColumnType("integer") - .HasColumnName("id"); - - b1.HasKey("CharacterId"); - - b1.ToTable("characters"); - - b1.WithOwner() - .HasForeignKey("CharacterId") - .HasConstraintName("fk_characters_characters_id"); - - b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterAttributes", "Attributes", b2 => - { - b2.Property("CharacterCharacteristicsCharacterId") - .HasColumnType("integer") - .HasColumnName("id"); - - b2.Property("Agility") - .HasColumnType("integer") - .HasColumnName("agility"); - - b2.Property("Points") - .HasColumnType("integer") - .HasColumnName("attribute_points"); - - b2.Property("Strength") - .HasColumnType("integer") - .HasColumnName("strength"); - - b2.HasKey("CharacterCharacteristicsCharacterId"); - - b2.ToTable("characters"); - - b2.WithOwner() - .HasForeignKey("CharacterCharacteristicsCharacterId") - .HasConstraintName("fk_characters_characters_id"); - }); - - b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterSkills", "Skills", b2 => - { - b2.Property("CharacterCharacteristicsCharacterId") - .HasColumnType("integer") - .HasColumnName("id"); - - b2.Property("Athletics") - .HasColumnType("integer") - .HasColumnName("athletics"); - - b2.Property("IronFlesh") - .HasColumnType("integer") - .HasColumnName("iron_flesh"); - - b2.Property("MountedArchery") - .HasColumnType("integer") - .HasColumnName("mounted_archery"); - - b2.Property("Points") - .HasColumnType("integer") - .HasColumnName("skill_points"); - - b2.Property("PowerDraw") - .HasColumnType("integer") - .HasColumnName("power_draw"); - - b2.Property("PowerStrike") - .HasColumnType("integer") - .HasColumnName("power_strike"); - - b2.Property("PowerThrow") - .HasColumnType("integer") - .HasColumnName("power_throw"); - - b2.Property("Riding") - .HasColumnType("integer") - .HasColumnName("riding"); - - b2.Property("Shield") - .HasColumnType("integer") - .HasColumnName("shield"); - - b2.Property("WeaponMaster") - .HasColumnType("integer") - .HasColumnName("weapon_master"); - - b2.HasKey("CharacterCharacteristicsCharacterId"); - - b2.ToTable("characters"); - - b2.WithOwner() - .HasForeignKey("CharacterCharacteristicsCharacterId") - .HasConstraintName("fk_characters_characters_id"); - }); - - b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterWeaponProficiencies", "WeaponProficiencies", b2 => - { - b2.Property("CharacterCharacteristicsCharacterId") - .HasColumnType("integer") - .HasColumnName("id"); - - b2.Property("Bow") - .HasColumnType("integer") - .HasColumnName("bow"); - - b2.Property("Crossbow") - .HasColumnType("integer") - .HasColumnName("crossbow"); - - b2.Property("OneHanded") - .HasColumnType("integer") - .HasColumnName("one_handed"); - - b2.Property("Points") - .HasColumnType("integer") - .HasColumnName("weapon_proficiency_points"); - - b2.Property("Polearm") - .HasColumnType("integer") - .HasColumnName("polearm"); - - b2.Property("Throwing") - .HasColumnType("integer") - .HasColumnName("throwing"); - - b2.Property("TwoHanded") - .HasColumnType("integer") - .HasColumnName("two_handed"); - - b2.HasKey("CharacterCharacteristicsCharacterId"); - - b2.ToTable("characters"); - - b2.WithOwner() - .HasForeignKey("CharacterCharacteristicsCharacterId") - .HasConstraintName("fk_characters_characters_id"); - }); - - b1.Navigation("Attributes") - .IsRequired(); - - b1.Navigation("Skills") - .IsRequired(); - - b1.Navigation("WeaponProficiencies") - .IsRequired(); - }); - - b.OwnsMany("Crpg.Domain.Entities.Characters.CharacterStatistics", "Statistics", b1 => - { - b1.Property("CharacterId") - .HasColumnType("integer") - .HasColumnName("character_id"); - - b1.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); - - b1.Property("Assists") - .HasColumnType("integer") - .HasColumnName("assists"); - - b1.Property("Deaths") - .HasColumnType("integer") - .HasColumnName("deaths"); - - b1.Property("GameMode") - .HasColumnType("game_mode") - .HasColumnName("game_mode"); - - b1.Property("Kills") - .HasColumnType("integer") - .HasColumnName("kills"); - - b1.Property("PlayTime") - .HasColumnType("interval") - .HasColumnName("play_time"); - - b1.HasKey("CharacterId", "Id") - .HasName("pk_character_statistics"); - - b1.ToTable("character_statistics", (string)null); - - b1.WithOwner("Character") - .HasForeignKey("CharacterId") - .HasConstraintName("fk_character_statistics_characters_character_id"); - - b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterRating", "Rating", b2 => - { - b2.Property("CharacterStatisticsCharacterId") - .HasColumnType("integer") - .HasColumnName("character_id"); - - b2.Property("CharacterStatisticsId") - .HasColumnType("integer") - .HasColumnName("id"); - - b2.Property("CompetitiveValue") - .HasColumnType("real") - .HasColumnName("competitive_rating"); - - b2.Property("Deviation") - .HasColumnType("real") - .HasColumnName("rating_deviation"); - - b2.Property("Value") - .HasColumnType("real") - .HasColumnName("rating"); - - b2.Property("Volatility") - .HasColumnType("real") - .HasColumnName("rating_volatility"); - - b2.HasKey("CharacterStatisticsCharacterId", "CharacterStatisticsId"); - - b2.ToTable("character_statistics"); - - b2.WithOwner() - .HasForeignKey("CharacterStatisticsCharacterId", "CharacterStatisticsId") - .HasConstraintName("fk_character_statistics_character_statistics_character_id_id"); - }); - - b1.Navigation("Character"); - - b1.Navigation("Rating") - .IsRequired(); - }); - - b.Navigation("Characteristics") - .IsRequired(); - - b.Navigation("Statistics"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => - { - b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") - .WithMany("ArmoryBorrowedItems") - .HasForeignKey("BorrowerClanId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_borrowed_items_clans_borrower_clan_id"); - - b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Borrower") - .WithMany("ArmoryBorrowedItems") - .HasForeignKey("BorrowerUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_borrowed_items_clan_members_borrower_user_id"); - - b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") - .WithOne("ClanArmoryBorrowedItem") - .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_borrowed_items_user_items_user_item_id"); - - b.HasOne("Crpg.Domain.Entities.Items.ClanArmoryItem", "ArmoryItem") - .WithOne("BorrowedItem") - .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_borrowed_items_clan_armory_items_user_item_id"); - - b.Navigation("ArmoryItem"); - - b.Navigation("Borrower"); - - b.Navigation("Clan"); - - b.Navigation("UserItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => - { - b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") - .WithMany("Invitations") - .HasForeignKey("ClanId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_invitations_clans_clan_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "Invitee") - .WithMany() - .HasForeignKey("InviteeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_invitations_users_invitee_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "Inviter") - .WithMany() - .HasForeignKey("InviterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_invitations_users_inviter_id"); - - b.Navigation("Clan"); - - b.Navigation("Invitee"); - - b.Navigation("Inviter"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => - { - b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") - .WithMany("Members") - .HasForeignKey("ClanId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_members_clans_clan_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithOne("ClanMembership") - .HasForeignKey("Crpg.Domain.Entities.Clans.ClanMember", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_members_users_user_id"); - - b.Navigation("Clan"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .HasConstraintName("fk_game_events_users_user_id"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => - { - b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") - .WithMany("ArmoryItems") - .HasForeignKey("LenderClanId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_items_clans_lender_clan_id"); - - b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Lender") - .WithMany("ArmoryItems") - .HasForeignKey("LenderUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_items_clan_members_lender_user_id"); - - b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") - .WithOne("ClanArmoryItem") - .HasForeignKey("Crpg.Domain.Entities.Items.ClanArmoryItem", "UserItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_clan_armory_items_user_items_user_item_id"); - - b.Navigation("Clan"); - - b.Navigation("Lender"); - - b.Navigation("UserItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => - { - b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") - .WithMany("EquippedItems") - .HasForeignKey("CharacterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_equipped_items_characters_character_id"); - - b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") - .WithMany("EquippedItems") - .HasForeignKey("UserItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_equipped_items_user_items_user_item_id"); - - b.Navigation("Character"); - - b.Navigation("UserItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => - { - b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "PrimaryWeapon", b1 => - { - b1.Property("ItemId") - .HasColumnType("text") - .HasColumnName("id"); - - b1.Property("Accuracy") - .HasColumnType("integer") - .HasColumnName("primary_accuracy"); - - b1.Property("Balance") - .HasColumnType("real") - .HasColumnName("primary_balance"); - - b1.Property("BodyArmor") - .HasColumnType("integer") - .HasColumnName("primary_body_armor"); - - b1.Property("Class") - .HasColumnType("weapon_class") - .HasColumnName("primary_class"); - - b1.Property("Flags") - .HasColumnType("bigint") - .HasColumnName("primary_flags"); - - b1.Property("Handling") - .HasColumnType("integer") - .HasColumnName("primary_handling"); - - b1.Property("ItemUsage") - .IsRequired() - .HasColumnType("text") - .HasColumnName("primary_weapon_item_usage"); - - b1.Property("Length") - .HasColumnType("integer") - .HasColumnName("primary_length"); - - b1.Property("MissileSpeed") - .HasColumnType("integer") - .HasColumnName("primary_missile_speed"); - - b1.Property("StackAmount") - .HasColumnType("integer") - .HasColumnName("primary_stack_amount"); - - b1.Property("SwingDamage") - .HasColumnType("integer") - .HasColumnName("primary_swing_damage"); - - b1.Property("SwingDamageType") - .HasColumnType("damage_type") - .HasColumnName("primary_swing_damage_type"); - - b1.Property("SwingSpeed") - .HasColumnType("integer") - .HasColumnName("primary_swing_speed"); - - b1.Property("ThrustDamage") - .HasColumnType("integer") - .HasColumnName("primary_thrust_damage"); - - b1.Property("ThrustDamageType") - .HasColumnType("damage_type") - .HasColumnName("primary_thrust_damage_type"); - - b1.Property("ThrustSpeed") - .HasColumnType("integer") - .HasColumnName("primary_thrust_speed"); - - b1.HasKey("ItemId"); - - b1.ToTable("items"); - - b1.WithOwner() - .HasForeignKey("ItemId") - .HasConstraintName("fk_items_items_id"); - }); - - b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "SecondaryWeapon", b1 => - { - b1.Property("ItemId") - .HasColumnType("text") - .HasColumnName("id"); - - b1.Property("Accuracy") - .HasColumnType("integer") - .HasColumnName("secondary_accuracy"); - - b1.Property("Balance") - .HasColumnType("real") - .HasColumnName("secondary_balance"); - - b1.Property("BodyArmor") - .HasColumnType("integer") - .HasColumnName("secondary_body_armor"); - - b1.Property("Class") - .HasColumnType("weapon_class") - .HasColumnName("secondary_class"); - - b1.Property("Flags") - .HasColumnType("bigint") - .HasColumnName("secondary_flags"); - - b1.Property("Handling") - .HasColumnType("integer") - .HasColumnName("secondary_handling"); - - b1.Property("ItemUsage") - .IsRequired() - .HasColumnType("text") - .HasColumnName("secondary_weapon_item_usage"); - - b1.Property("Length") - .HasColumnType("integer") - .HasColumnName("secondary_length"); - - b1.Property("MissileSpeed") - .HasColumnType("integer") - .HasColumnName("secondary_missile_speed"); - - b1.Property("StackAmount") - .HasColumnType("integer") - .HasColumnName("secondary_stack_amount"); - - b1.Property("SwingDamage") - .HasColumnType("integer") - .HasColumnName("secondary_swing_damage"); - - b1.Property("SwingDamageType") - .HasColumnType("damage_type") - .HasColumnName("secondary_swing_damage_type"); - - b1.Property("SwingSpeed") - .HasColumnType("integer") - .HasColumnName("secondary_swing_speed"); - - b1.Property("ThrustDamage") - .HasColumnType("integer") - .HasColumnName("secondary_thrust_damage"); - - b1.Property("ThrustDamageType") - .HasColumnType("damage_type") - .HasColumnName("secondary_thrust_damage_type"); - - b1.Property("ThrustSpeed") - .HasColumnType("integer") - .HasColumnName("secondary_thrust_speed"); - - b1.HasKey("ItemId"); - - b1.ToTable("items"); - - b1.WithOwner() - .HasForeignKey("ItemId") - .HasConstraintName("fk_items_items_id"); - }); - - b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "TertiaryWeapon", b1 => - { - b1.Property("ItemId") - .HasColumnType("text") - .HasColumnName("id"); - - b1.Property("Accuracy") - .HasColumnType("integer") - .HasColumnName("tertiary_accuracy"); - - b1.Property("Balance") - .HasColumnType("real") - .HasColumnName("tertiary_balance"); - - b1.Property("BodyArmor") - .HasColumnType("integer") - .HasColumnName("tertiary_body_armor"); - - b1.Property("Class") - .HasColumnType("weapon_class") - .HasColumnName("tertiary_class"); - - b1.Property("Flags") - .HasColumnType("bigint") - .HasColumnName("tertiary_flags"); - - b1.Property("Handling") - .HasColumnType("integer") - .HasColumnName("tertiary_handling"); - - b1.Property("ItemUsage") - .IsRequired() - .HasColumnType("text") - .HasColumnName("tertiary_weapon_item_usage"); - - b1.Property("Length") - .HasColumnType("integer") - .HasColumnName("tertiary_length"); - - b1.Property("MissileSpeed") - .HasColumnType("integer") - .HasColumnName("tertiary_missile_speed"); - - b1.Property("StackAmount") - .HasColumnType("integer") - .HasColumnName("tertiary_stack_amount"); - - b1.Property("SwingDamage") - .HasColumnType("integer") - .HasColumnName("tertiary_swing_damage"); - - b1.Property("SwingDamageType") - .HasColumnType("damage_type") - .HasColumnName("tertiary_swing_damage_type"); - - b1.Property("SwingSpeed") - .HasColumnType("integer") - .HasColumnName("tertiary_swing_speed"); - - b1.Property("ThrustDamage") - .HasColumnType("integer") - .HasColumnName("tertiary_thrust_damage"); - - b1.Property("ThrustDamageType") - .HasColumnType("damage_type") - .HasColumnName("tertiary_thrust_damage_type"); - - b1.Property("ThrustSpeed") - .HasColumnType("integer") - .HasColumnName("tertiary_thrust_speed"); - - b1.HasKey("ItemId"); - - b1.ToTable("items"); - - b1.WithOwner() - .HasForeignKey("ItemId") - .HasConstraintName("fk_items_items_id"); - }); - - b.OwnsOne("Crpg.Domain.Entities.Items.ItemArmorComponent", "Armor", b1 => - { - b1.Property("ItemId") - .HasColumnType("text") - .HasColumnName("id"); - - b1.Property("ArmArmor") - .HasColumnType("integer") - .HasColumnName("armor_arm"); - - b1.Property("BodyArmor") - .HasColumnType("integer") - .HasColumnName("armor_body"); - - b1.Property("FamilyType") - .HasColumnType("integer") - .HasColumnName("armor_family_type"); - - b1.Property("HeadArmor") - .HasColumnType("integer") - .HasColumnName("armor_head"); - - b1.Property("LegArmor") - .HasColumnType("integer") - .HasColumnName("armor_leg"); - - b1.Property("MaterialType") - .HasColumnType("integer") - .HasColumnName("armor_material_type"); - - b1.HasKey("ItemId"); - - b1.ToTable("items"); - - b1.WithOwner() - .HasForeignKey("ItemId") - .HasConstraintName("fk_items_items_id"); - }); - - b.OwnsOne("Crpg.Domain.Entities.Items.ItemMountComponent", "Mount", b1 => - { - b1.Property("ItemId") - .HasColumnType("text") - .HasColumnName("id"); - - b1.Property("BodyLength") - .HasColumnType("integer") - .HasColumnName("mount_body_length"); - - b1.Property("ChargeDamage") - .HasColumnType("integer") - .HasColumnName("mount_charge_damage"); - - b1.Property("FamilyType") - .HasColumnType("integer") - .HasColumnName("mount_family_type"); - - b1.Property("HitPoints") - .HasColumnType("integer") - .HasColumnName("mount_hit_points"); - - b1.Property("Maneuver") - .HasColumnType("integer") - .HasColumnName("mount_maneuver"); - - b1.Property("Speed") - .HasColumnType("integer") - .HasColumnName("mount_speed"); - - b1.HasKey("ItemId"); - - b1.ToTable("items"); - - b1.WithOwner() - .HasForeignKey("ItemId") - .HasConstraintName("fk_items_items_id"); - }); - - b.Navigation("Armor"); - - b.Navigation("Mount"); - - b.Navigation("PrimaryWeapon"); - - b.Navigation("SecondaryWeapon"); - - b.Navigation("TertiaryWeapon"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => - { - b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_item_stacks_items_item_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") - .WithMany("Items") - .HasForeignKey("PartyId") - .OnDelete(DeleteBehavior.Cascade) - .HasConstraintName("fk_item_stacks_parties_party_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.PartyTransferOffer", "PartyTransferOffer") - .WithMany("Items") - .HasForeignKey("PartyTransferOfferId") - .OnDelete(DeleteBehavior.Cascade) - .HasConstraintName("fk_item_stacks_party_transfer_offers_party_transfer_offer_id"); - - b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") - .WithMany("Items") - .HasForeignKey("SettlementId") - .OnDelete(DeleteBehavior.Cascade) - .HasConstraintName("fk_item_stacks_settlements_settlement_id"); - - b.Navigation("Item"); - - b.Navigation("Party"); - - b.Navigation("PartyTransferOffer"); - - b.Navigation("Settlement"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => - { - b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") - .WithOne("PersonalItem") - .HasForeignKey("Crpg.Domain.Entities.Items.PersonalItem", "UserItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_personal_items_user_items_user_item_id"); - - b.Navigation("UserItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => - { - b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") - .WithMany("UserItems") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_items_items_item_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany("Items") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_items_users_user_id"); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany("ItemPresets") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_item_presets_users_user_id"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => - { - b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.SetNull) - .HasConstraintName("fk_user_item_preset_slots_items_item_id"); - - b.HasOne("Crpg.Domain.Entities.Items.UserItemPreset", "UserItemPreset") - .WithMany("Slots") - .HasForeignKey("UserItemPresetId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_item_preset_slots_user_item_presets_user_item_preset_id"); - - b.Navigation("Item"); - - b.Navigation("UserItemPreset"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => - { - b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") - .WithOne("Limitations") - .HasForeignKey("Crpg.Domain.Entities.Limitations.CharacterLimitations", "CharacterId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_character_limitations_characters_character_id"); - - b.Navigation("Character"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "Seller") - .WithMany("MarketplaceListings") - .HasForeignKey("SellerId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired() - .HasConstraintName("fk_marketplace_listings_users_seller_id"); - - b.Navigation("Seller"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => - { - b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") - .WithMany() - .HasForeignKey("ItemId") - .HasConstraintName("fk_marketplace_listing_assets_items_item_id"); - - b.HasOne("Crpg.Domain.Entities.Marketplace.MarketplaceListing", "MarketplaceListing") - .WithMany("Assets") - .HasForeignKey("MarketplaceListingId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_marketplace_listing_assets_marketplace_listings_marketplace"); - - b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") - .WithMany("MarketplaceListingAssets") - .HasForeignKey("UserItemId") - .OnDelete(DeleteBehavior.Restrict) - .HasConstraintName("fk_marketplace_listing_assets_user_items_user_item_id"); - - b.Navigation("Item"); - - b.Navigation("MarketplaceListing"); - - b.Navigation("UserItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany("Notifications") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_notifications_users_user_id"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => - { - b.HasOne("Crpg.Domain.Entities.Notifications.UserNotification", null) - .WithMany("Metadata") - .HasForeignKey("UserNotificationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_notification_metadata_user_notifications_user_notifica"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => - { - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "CurrentBattle") - .WithMany() - .HasForeignKey("CurrentBattleId") - .HasConstraintName("fk_parties_battles_current_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.Party", "CurrentParty") - .WithMany() - .HasForeignKey("CurrentPartyId") - .HasConstraintName("fk_parties_parties_current_party_id"); - - b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "CurrentSettlement") - .WithMany() - .HasForeignKey("CurrentSettlementId") - .HasConstraintName("fk_parties_settlements_current_settlement_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithOne("Party") - .HasForeignKey("Crpg.Domain.Entities.Parties.Party", "Id") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_parties_users_id"); - - b.Navigation("CurrentBattle"); - - b.Navigation("CurrentParty"); - - b.Navigation("CurrentSettlement"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => - { - b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") - .WithMany("Orders") - .HasForeignKey("PartyId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_party_orders_parties_party_id"); - - b.HasOne("Crpg.Domain.Entities.Battles.Battle", "TargetedBattle") - .WithMany() - .HasForeignKey("TargetedBattleId") - .HasConstraintName("fk_party_orders_battles_targeted_battle_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetedParty") - .WithMany() - .HasForeignKey("TargetedPartyId") - .HasConstraintName("fk_party_orders_parties_targeted_party_id"); - - b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "TargetedSettlement") - .WithMany() - .HasForeignKey("TargetedSettlementId") - .HasConstraintName("fk_party_orders_settlements_targeted_settlement_id"); - - b.Navigation("Party"); - - b.Navigation("TargetedBattle"); - - b.Navigation("TargetedParty"); - - b.Navigation("TargetedSettlement"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => - { - b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") - .WithMany() - .HasForeignKey("PartyId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_party_transfer_offers_parties_party_id"); - - b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetParty") - .WithMany() - .HasForeignKey("TargetPartyId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_party_transfer_offers_parties_target_party_id"); - - b.Navigation("Party"); - - b.Navigation("TargetParty"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => - { - b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") - .WithMany() - .HasForeignKey("QuestDefinitionId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired() - .HasConstraintName("fk_user_quests_quest_definitions_quest_definition_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_user_quests_users_user_id"); - - b.Navigation("QuestDefinition"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => - { - b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") - .WithMany() - .HasForeignKey("QuestDefinitionId") - .OnDelete(DeleteBehavior.Restrict) - .IsRequired() - .HasConstraintName("fk_weekly_quest_assignments_quest_definitions_quest_definition"); - - b.Navigation("QuestDefinition"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => - { - b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedByUser") - .WithMany() - .HasForeignKey("RestrictedByUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_restrictions_users_restricted_by_user_id"); - - b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedUser") - .WithMany("Restrictions") - .HasForeignKey("RestrictedUserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_restrictions_users_restricted_user_id"); - - b.Navigation("RestrictedByUser"); - - b.Navigation("RestrictedUser"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => - { - b.HasOne("Crpg.Domain.Entities.Parties.Party", "Owner") - .WithMany("OwnedSettlements") - .HasForeignKey("OwnerId") - .HasConstraintName("fk_settlements_parties_owner_id"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => - { - b.HasOne("Crpg.Domain.Entities.Characters.Character", "ActiveCharacter") - .WithOne() - .HasForeignKey("Crpg.Domain.Entities.Users.User", "ActiveCharacterId") - .HasConstraintName("fk_users_characters_active_character_id"); - - b.Navigation("ActiveCharacter"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => - { - b.Navigation("Metadata"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => - { - b.Navigation("FighterApplications"); - - b.Navigation("Fighters"); - - b.Navigation("MercenaryApplications"); - - b.Navigation("Participants"); - - b.Navigation("SideBriefings"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => - { - b.Navigation("Statistic"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => - { - b.Navigation("EquippedItems"); - - b.Navigation("Limitations"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => - { - b.Navigation("ArmoryBorrowedItems"); - - b.Navigation("ArmoryItems"); - - b.Navigation("Invitations"); - - b.Navigation("Members"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => - { - b.Navigation("ArmoryBorrowedItems"); - - b.Navigation("ArmoryItems"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => - { - b.Navigation("BorrowedItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => - { - b.Navigation("UserItems"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => - { - b.Navigation("ClanArmoryBorrowedItem"); - - b.Navigation("ClanArmoryItem"); - - b.Navigation("EquippedItems"); - - b.Navigation("MarketplaceListingAssets"); - - b.Navigation("PersonalItem"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => - { - b.Navigation("Slots"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => - { - b.Navigation("Assets"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => - { - b.Navigation("Metadata"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => - { - b.Navigation("Items"); - - b.Navigation("Orders"); - - b.Navigation("OwnedSettlements"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => - { - b.Navigation("Items"); - }); - - modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => - { - b.Navigation("Characters"); - - b.Navigation("ClanMembership"); - - b.Navigation("ItemPresets"); - - b.Navigation("Items"); - - b.Navigation("MarketplaceListings"); - - b.Navigation("Notifications"); - - b.Navigation("Party"); - - b.Navigation("Restrictions"); - }); -#pragma warning restore 612, 618 - } - } -} +// +using System; +using System.Collections.Generic; +using Crpg.Domain.Entities; +using Crpg.Domain.Entities.ActivityLogs; +using Crpg.Domain.Entities.Battles; +using Crpg.Domain.Entities.Characters; +using Crpg.Domain.Entities.Clans; +using Crpg.Domain.Entities.Items; +using Crpg.Domain.Entities.Marketplace; +using Crpg.Domain.Entities.Notifications; +using Crpg.Domain.Entities.Parties; +using Crpg.Domain.Entities.Quests; +using Crpg.Domain.Entities.Restrictions; +using Crpg.Domain.Entities.Servers; +using Crpg.Domain.Entities.Settlements; +using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; +using Crpg.Domain.Entities.Users; +using Crpg.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetTopologySuite.Geometries; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Crpg.Persistence.Migrations +{ + [DbContext(typeof(CrpgDbContext))] + partial class CrpgDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "activity_log_type", new[] { "battle_apply_as_mercenary", "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked", "battle_participant_leaved", "character_created", "character_deleted", "character_earned", "character_rating_reset", "character_respecialized", "character_retired", "character_rewarded", "chat_message_sent", "clan_application_accepted", "clan_application_created", "clan_application_declined", "clan_armory_add_item", "clan_armory_borrow_item", "clan_armory_remove_item", "clan_armory_return_item", "clan_created", "clan_deleted", "clan_member_kicked", "clan_member_leaved", "clan_member_role_edited", "item_bought", "item_broke", "item_reforged", "item_repaired", "item_returned", "item_sold", "item_upgraded", "marketplace_listing_accepted", "marketplace_listing_cancelled", "marketplace_listing_created", "marketplace_listing_expired", "marketplace_listing_invalidated", "quest_rerolled", "quest_reward_claimed", "server_joined", "team_hit", "team_hit_reported", "team_hit_reported_user_kicked", "user_created", "user_deleted", "user_renamed", "user_rewarded" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_fighter_application_status", new[] { "accepted", "declined", "intent", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_mercenary_application_status", new[] { "accepted", "declined", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_participant_type", new[] { "clan_member", "mercenary", "party" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_phase", new[] { "end", "hiring", "live", "preparation", "scheduled" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_side", new[] { "attacker", "defender" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_class", new[] { "archer", "cavalry", "crossbowman", "infantry", "mounted_archer", "peasant", "shock_infantry", "skirmisher" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_status", new[] { "accepted", "declined", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_type", new[] { "offer", "request" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_member_role", new[] { "leader", "member", "officer" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "culture", new[] { "aserai", "battania", "empire", "khuzait", "looters", "neutral", "sturgia", "vlandia" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "damage_type", new[] { "blunt", "cut", "pierce", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "game_mode", new[] { "crpg_battle", "crpg_captain", "crpg_conquest", "crpg_duel", "crpg_siege", "crpg_skirmish", "crpg_team_deathmatch", "crpg_unknown_game_mode", "crpgdtv" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_type", new[] { "arrows", "banner", "body_armor", "bolts", "bow", "bullets", "crossbow", "hand_armor", "head_armor", "leg_armor", "mount", "mount_harness", "musket", "one_handed_weapon", "pistol", "polearm", "shield", "shoulder_armor", "thrown", "two_handed_weapon", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "languages", new[] { "be", "bg", "cs", "da", "de", "el", "en", "es", "fi", "fr", "hr", "hu", "it", "lv", "nl", "no", "pl", "pt", "ro", "ru", "sr", "sv", "tr", "uk", "zh" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "marketplace_listing_asset_side", new[] { "offered", "requested" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_state", new[] { "read", "unread" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_type", new[] { "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked_to_ex_participant", "character_rewarded_to_user", "clan_application_accepted_to_user", "clan_application_created_to_officers", "clan_application_created_to_user", "clan_application_declined_to_user", "clan_armory_borrow_item_to_lender", "clan_armory_remove_item_to_borrower", "clan_member_kicked_to_ex_member", "clan_member_leaved_to_leader", "clan_member_role_changed_to_user", "item_returned", "marketplace_listing_accepted_to_buyer", "marketplace_listing_accepted_to_seller", "marketplace_listing_expired", "marketplace_listing_invalidated", "user_rewarded_to_user" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_order_type", new[] { "attack_party", "attack_settlement", "follow_party", "join_battle", "move_to_point", "move_to_settlement", "transfer_offer_party" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_status", new[] { "awaiting_battle_join_decision", "awaiting_party_offer_decision", "idle", "idle_in_settlement", "in_battle", "recruiting_in_settlement" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_transfer_offer_status", new[] { "intent", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "platform", new[] { "epic_games", "microsoft", "steam" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_aggregation_type", new[] { "count", "sum" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_type", new[] { "daily", "weekly" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "region", new[] { "as", "eu", "na", "oc" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "restriction_type", new[] { "all", "chat", "join" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "role", new[] { "admin", "game_admin", "moderator", "user" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "settlement_type", new[] { "castle", "town", "village" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "terrain_type", new[] { "barrier", "deep_water", "plain", "shallow_water", "sparse_forest", "thick_forest" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "theme_equipment_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "weapon_class", new[] { "arrow", "banner", "bolt", "boulder", "bow", "cartridge", "crossbow", "dagger", "javelin", "large_shield", "low_grip_polearm", "mace", "musket", "one_handed_axe", "one_handed_polearm", "one_handed_sword", "pick", "pistol", "small_shield", "stone", "throwing_axe", "throwing_knife", "two_handed_axe", "two_handed_mace", "two_handed_polearm", "two_handed_sword", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("BattleParticipantStatistic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Assists") + .HasColumnType("integer") + .HasColumnName("assists"); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("Deaths") + .HasColumnType("integer") + .HasColumnName("deaths"); + + b.Property("Kills") + .HasColumnType("integer") + .HasColumnName("kills"); + + b.Property("ParticipantId") + .HasColumnType("integer") + .HasColumnName("participant_id"); + + b.Property("Participated") + .HasColumnType("boolean") + .HasColumnName("participated"); + + b.HasKey("Id") + .HasName("pk_battle_participant_statistic"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_participant_statistic_battle_id"); + + b.HasIndex("ParticipantId") + .IsUnique() + .HasDatabaseName("ix_battle_participant_statistic_participant_id"); + + b.ToTable("battle_participant_statistic", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Type") + .HasColumnType("activity_log_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_activity_logs"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_activity_logs_user_id"); + + b.HasIndex("CreatedAt", "UserId") + .HasDatabaseName("ix_activity_logs_created_at_user_id"); + + b.ToTable("activity_logs", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => + { + b.Property("ActivityLogId") + .HasColumnType("integer") + .HasColumnName("activity_log_id"); + + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("ActivityLogId", "Key") + .HasName("pk_activity_log_metadata"); + + b.ToTable("activity_log_metadata", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Phase") + .HasColumnType("battle_phase") + .HasColumnName("phase"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("ScheduledFor") + .HasColumnType("timestamp with time zone") + .HasColumnName("scheduled_for"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battles"); + + b.ToTable("battles", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("Commander") + .HasColumnType("boolean") + .HasColumnName("commander"); + + b.Property("ParticipantSlots") + .HasColumnType("integer") + .HasColumnName("participant_slots"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("SettlementId") + .HasColumnType("integer") + .HasColumnName("settlement_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.HasKey("Id") + .HasName("pk_battle_fighters"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_fighters_battle_id"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_battle_fighters_party_id"); + + b.HasIndex("SettlementId") + .HasDatabaseName("ix_battle_fighters_settlement_id"); + + b.ToTable("battle_fighters", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Status") + .HasColumnType("battle_fighter_application_status") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battle_fighter_applications"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_fighter_applications_battle_id"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_battle_fighter_applications_party_id"); + + b.ToTable("battle_fighter_applications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Status") + .HasColumnType("battle_mercenary_application_status") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Wage") + .HasColumnType("integer") + .HasColumnName("wage"); + + b.HasKey("Id") + .HasName("pk_battle_mercenary_applications"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_mercenary_applications_battle_id"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_battle_mercenary_applications_character_id"); + + b.ToTable("battle_mercenary_applications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CaptainFighterId") + .HasColumnType("integer") + .HasColumnName("captain_fighter_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("MercenaryApplicationId") + .HasColumnType("integer") + .HasColumnName("mercenary_application_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Type") + .HasColumnType("battle_participant_type") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_battle_participants"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_participants_battle_id"); + + b.HasIndex("CaptainFighterId") + .HasDatabaseName("ix_battle_participants_captain_fighter_id"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_battle_participants_character_id"); + + b.HasIndex("MercenaryApplicationId") + .HasDatabaseName("ix_battle_participants_mercenary_application_id"); + + b.ToTable("battle_participants", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battle_side_briefings"); + + b.HasIndex("BattleId", "Side") + .IsUnique() + .HasDatabaseName("ix_battle_side_briefings_battle_id_side"); + + b.ToTable("battle_side_briefings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Class") + .HasColumnType("character_class") + .HasColumnName("class"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("ForTournament") + .HasColumnType("boolean") + .HasColumnName("for_tournament"); + + b.Property("Generation") + .HasColumnType("integer") + .HasColumnName("generation"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_characters"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_characters_user_id"); + + b.ToTable("characters", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArmoryTimeout") + .HasColumnType("interval") + .HasColumnName("armory_timeout"); + + b.Property("BannerKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("banner_key"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Discord") + .HasColumnType("text") + .HasColumnName("discord"); + + b.PrimitiveCollection("Languages") + .IsRequired() + .HasColumnType("languages[]") + .HasColumnName("languages"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("PrimaryColor") + .HasColumnType("bigint") + .HasColumnName("primary_color"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("SecondaryColor") + .HasColumnType("bigint") + .HasColumnName("secondary_color"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tag"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_clans"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_clans_name"); + + b.HasIndex("Tag") + .IsUnique() + .HasDatabaseName("ix_clans_tag"); + + b.ToTable("clans", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("BorrowerClanId") + .HasColumnType("integer") + .HasColumnName("borrower_clan_id"); + + b.Property("BorrowerUserId") + .HasColumnType("integer") + .HasColumnName("borrower_user_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_clan_armory_borrowed_items"); + + b.HasIndex("BorrowerClanId") + .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_clan_id"); + + b.HasIndex("BorrowerUserId") + .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_user_id"); + + b.ToTable("clan_armory_borrowed_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClanId") + .HasColumnType("integer") + .HasColumnName("clan_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("InviteeId") + .HasColumnType("integer") + .HasColumnName("invitee_id"); + + b.Property("InviterId") + .HasColumnType("integer") + .HasColumnName("inviter_id"); + + b.Property("Status") + .HasColumnType("clan_invitation_status") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("clan_invitation_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_clan_invitations"); + + b.HasIndex("ClanId") + .HasDatabaseName("ix_clan_invitations_clan_id"); + + b.HasIndex("InviteeId") + .HasDatabaseName("ix_clan_invitations_invitee_id"); + + b.HasIndex("InviterId") + .HasDatabaseName("ix_clan_invitations_inviter_id"); + + b.ToTable("clan_invitations", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("ClanId") + .HasColumnType("integer") + .HasColumnName("clan_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Role") + .HasColumnType("clan_member_role") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserId") + .HasName("pk_clan_members"); + + b.HasIndex("ClanId") + .HasDatabaseName("ix_clan_members_clan_id"); + + b.ToTable("clan_members", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventData") + .HasColumnType("jsonb") + .HasColumnName("event_data"); + + b.Property("GameMode") + .HasColumnType("game_mode") + .HasColumnName("game_mode"); + + b.Property("Instance") + .IsRequired() + .HasColumnType("text") + .HasColumnName("instance"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_game_events"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("ix_game_events_created_at"); + + b.HasIndex("UserId", "Type", "CreatedAt") + .HasDatabaseName("ix_game_events_user_id_type_created_at"); + + b.ToTable("game_events", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("LenderClanId") + .HasColumnType("integer") + .HasColumnName("lender_clan_id"); + + b.Property("LenderUserId") + .HasColumnType("integer") + .HasColumnName("lender_user_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_clan_armory_items"); + + b.HasIndex("LenderClanId") + .HasDatabaseName("ix_clan_armory_items_lender_clan_id"); + + b.HasIndex("LenderUserId") + .HasDatabaseName("ix_clan_armory_items_lender_user_id"); + + b.ToTable("clan_armory_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Slot") + .HasColumnType("item_slot") + .HasColumnName("slot"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.HasKey("CharacterId", "Slot") + .HasName("pk_equipped_items"); + + b.HasIndex("UserItemId") + .HasDatabaseName("ix_equipped_items_user_item_id"); + + b.ToTable("equipped_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.Property("Id") + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("BaseId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("base_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Culture") + .HasColumnType("culture") + .HasColumnName("culture"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("Rank") + .HasColumnType("integer") + .HasColumnName("rank"); + + b.Property("Requirement") + .HasColumnType("integer") + .HasColumnName("requirement"); + + b.Property("Tier") + .HasColumnType("real") + .HasColumnName("tier"); + + b.Property("Type") + .HasColumnType("item_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Weight") + .HasColumnType("real") + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_items"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ItemId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("PartyTransferOfferId") + .HasColumnType("integer") + .HasColumnName("party_transfer_offer_id"); + + b.Property("SettlementId") + .HasColumnType("integer") + .HasColumnName("settlement_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_item_stacks"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_item_stacks_item_id"); + + b.HasIndex("PartyId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_party_id_item_id") + .HasFilter("party_id IS NOT NULL"); + + b.HasIndex("PartyTransferOfferId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_party_transfer_offer_id_item_id") + .HasFilter("party_transfer_offer_id IS NOT NULL"); + + b.HasIndex("SettlementId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_settlement_id_item_id") + .HasFilter("settlement_id IS NOT NULL"); + + b.ToTable("item_stacks", null, t => + { + t.HasCheckConstraint("CK_item_stacks_single_owner", "(party_id IS NOT NULL)::int + (settlement_id IS NOT NULL)::int + (party_transfer_offer_id IS NOT NULL)::int = 1"); + }); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_personal_items"); + + b.ToTable("personal_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("IsBroken") + .HasColumnType("boolean") + .HasColumnName("is_broken"); + + b.Property("ItemId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_items"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_user_items_item_id"); + + b.HasIndex("UserId", "ItemId") + .HasDatabaseName("ix_user_items_user_id_item_id"); + + b.ToTable("user_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_item_presets"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_item_presets_user_id"); + + b.ToTable("user_item_presets", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => + { + b.Property("UserItemPresetId") + .HasColumnType("integer") + .HasColumnName("user_item_preset_id"); + + b.Property("Slot") + .HasColumnType("item_slot") + .HasColumnName("slot"); + + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.HasKey("UserItemPresetId", "Slot") + .HasName("pk_user_item_preset_slots"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_user_item_preset_slots_item_id"); + + b.ToTable("user_item_preset_slots", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("LastRespecializeAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_respecialize_at"); + + b.HasKey("CharacterId") + .HasName("pk_character_limitations"); + + b.ToTable("character_limitations", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("GoldFee") + .HasColumnType("integer") + .HasColumnName("gold_fee"); + + b.Property("SellerId") + .HasColumnType("integer") + .HasColumnName("seller_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_marketplace_listings"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("ix_marketplace_listings_created_at"); + + b.HasIndex("ExpiresAt") + .HasDatabaseName("ix_marketplace_listings_expires_at"); + + b.HasIndex("SellerId", "CreatedAt") + .HasDatabaseName("ix_marketplace_listings_seller_id_created_at"); + + b.ToTable("marketplace_listings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("HeirloomPoints") + .HasColumnType("integer") + .HasColumnName("heirloom_points"); + + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("MarketplaceListingId") + .HasColumnType("integer") + .HasColumnName("marketplace_listing_id"); + + b.Property("Side") + .HasColumnType("marketplace_listing_asset_side") + .HasColumnName("side"); + + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.HasKey("Id") + .HasName("pk_marketplace_listing_assets"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_marketplace_listing_assets_item_id"); + + b.HasIndex("UserItemId") + .HasDatabaseName("ix_marketplace_listing_assets_user_item_id"); + + b.HasIndex("MarketplaceListingId", "Side") + .HasDatabaseName("ix_marketplace_listing_assets_marketplace_listing_id_side"); + + b.ToTable("marketplace_listing_assets", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("State") + .HasColumnType("notification_state") + .HasColumnName("state"); + + b.Property("Type") + .HasColumnType("notification_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_notifications"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_notifications_user_id"); + + b.ToTable("user_notifications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => + { + b.Property("UserNotificationId") + .HasColumnType("integer") + .HasColumnName("user_notification_id"); + + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("UserNotificationId", "Key") + .HasName("pk_user_notification_metadata"); + + b.ToTable("user_notification_metadata", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CurrentBattleId") + .HasColumnType("integer") + .HasColumnName("current_battle_id"); + + b.Property("CurrentPartyId") + .HasColumnType("integer") + .HasColumnName("current_party_id"); + + b.Property("CurrentSettlementId") + .HasColumnType("integer") + .HasColumnName("current_settlement_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Status") + .HasColumnType("party_status") + .HasColumnName("status"); + + b.Property("Troops") + .HasColumnType("real") + .HasColumnName("troops"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_parties"); + + b.HasIndex("CurrentBattleId") + .HasDatabaseName("ix_parties_current_battle_id"); + + b.HasIndex("CurrentPartyId") + .HasDatabaseName("ix_parties_current_party_id"); + + b.HasIndex("CurrentSettlementId") + .HasDatabaseName("ix_parties_current_settlement_id"); + + b.ToTable("parties", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderIndex") + .HasColumnType("integer") + .HasColumnName("order_index"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("TargetedBattleId") + .HasColumnType("integer") + .HasColumnName("targeted_battle_id"); + + b.Property("TargetedPartyId") + .HasColumnType("integer") + .HasColumnName("targeted_party_id"); + + b.Property("TargetedSettlementId") + .HasColumnType("integer") + .HasColumnName("targeted_settlement_id"); + + b.Property("Type") + .HasColumnType("party_order_type") + .HasColumnName("type"); + + b.Property("Waypoints") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("waypoints"); + + b.HasKey("Id") + .HasName("pk_party_orders"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_party_orders_party_id"); + + b.HasIndex("TargetedBattleId") + .HasDatabaseName("ix_party_orders_targeted_battle_id"); + + b.HasIndex("TargetedPartyId") + .HasDatabaseName("ix_party_orders_targeted_party_id"); + + b.HasIndex("TargetedSettlementId") + .HasDatabaseName("ix_party_orders_targeted_settlement_id"); + + b.ToTable("party_orders", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("Status") + .HasColumnType("party_transfer_offer_status") + .HasColumnName("status"); + + b.Property("TargetPartyId") + .HasColumnType("integer") + .HasColumnName("target_party_id"); + + b.Property("Troops") + .HasColumnType("real") + .HasColumnName("troops"); + + b.HasKey("Id") + .HasName("pk_party_transfer_offers"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_party_transfer_offers_party_id"); + + b.HasIndex("TargetPartyId") + .HasDatabaseName("ix_party_transfer_offers_target_party_id"); + + b.ToTable("party_transfer_offers", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.QuestDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AggregationField") + .HasColumnType("integer") + .HasColumnName("aggregation_field"); + + b.Property("AggregationType") + .HasColumnType("quest_aggregation_type") + .HasColumnName("aggregation_type"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventFiltersJson") + .HasColumnType("jsonb") + .HasColumnName("event_filters_json"); + + b.Property("EventType") + .HasColumnType("integer") + .HasColumnName("event_type"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("RequiredValue") + .HasColumnType("integer") + .HasColumnName("required_value"); + + b.Property("RewardExperience") + .HasColumnType("integer") + .HasColumnName("reward_experience"); + + b.Property("RewardGold") + .HasColumnType("integer") + .HasColumnName("reward_gold"); + + b.Property("Type") + .HasColumnType("quest_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_quest_definitions"); + + b.ToTable("quest_definitions", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("IsRewardClaimed") + .HasColumnType("boolean") + .HasColumnName("is_reward_claimed"); + + b.Property("QuestDefinitionId") + .HasColumnType("integer") + .HasColumnName("quest_definition_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_user_quests"); + + b.HasIndex("QuestDefinitionId") + .HasDatabaseName("ix_user_quests_quest_definition_id"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_quests_user_id"); + + b.ToTable("user_quests", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("QuestDefinitionId") + .HasColumnType("integer") + .HasColumnName("quest_definition_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_weekly_quest_assignments"); + + b.HasIndex("ExpiresAt") + .HasDatabaseName("ix_weekly_quest_assignments_expires_at"); + + b.HasIndex("QuestDefinitionId") + .HasDatabaseName("ix_weekly_quest_assignments_quest_definition_id"); + + b.ToTable("weekly_quest_assignments", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Duration") + .HasColumnType("interval") + .HasColumnName("duration"); + + b.Property("PublicReason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("public_reason"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RestrictedByUserId") + .HasColumnType("integer") + .HasColumnName("restricted_by_user_id"); + + b.Property("RestrictedUserId") + .HasColumnType("integer") + .HasColumnName("restricted_user_id"); + + b.Property("Type") + .HasColumnType("restriction_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_restrictions"); + + b.HasIndex("RestrictedByUserId") + .HasDatabaseName("ix_restrictions_restricted_by_user_id"); + + b.HasIndex("RestrictedUserId") + .HasDatabaseName("ix_restrictions_restricted_user_id"); + + b.ToTable("restrictions", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settings.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Discord") + .IsRequired() + .HasColumnType("text") + .HasColumnName("discord"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("HappyHours") + .IsRequired() + .HasColumnType("text") + .HasColumnName("happy_hours"); + + b.Property("ModDb") + .IsRequired() + .HasColumnType("text") + .HasColumnName("mod_db"); + + b.Property("Patreon") + .IsRequired() + .HasColumnType("text") + .HasColumnName("patreon"); + + b.Property("Reddit") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reddit"); + + b.Property("Steam") + .IsRequired() + .HasColumnType("text") + .HasColumnName("steam"); + + b.HasKey("Id") + .HasName("pk_settings"); + + b.ToTable("settings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Culture") + .HasColumnType("culture") + .HasColumnName("culture"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("owner_id"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("Scene") + .IsRequired() + .HasColumnType("text") + .HasColumnName("scene"); + + b.Property("Troops") + .HasColumnType("integer") + .HasColumnName("troops"); + + b.Property("Type") + .HasColumnType("settlement_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_settlements"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_settlements_owner_id"); + + b.HasIndex("Region", "Name") + .IsUnique() + .HasDatabaseName("ix_settlements_region_name"); + + b.ToTable("settlements", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Terrains.Terrain", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Boundary") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("boundary"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Type") + .HasColumnType("terrain_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_terrains"); + + b.ToTable("terrains", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_themes"); + + b.HasIndex("Name") + .HasDatabaseName("ix_themes_name"); + + b.ToTable("themes", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.ThemeEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveFromUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("active_from_utc"); + + b.Property("ActiveUntilUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("active_until_utc"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventThemeId") + .HasColumnType("integer") + .HasColumnName("event_theme_id"); + + b.Property("ExpMultiplier") + .HasColumnType("real") + .HasColumnName("exp_multiplier"); + + b.Property("GoldMultiplier") + .HasColumnType("real") + .HasColumnName("gold_multiplier"); + + b.Property("MinumumRequiredEquipmentSlotsMatchingTheme") + .HasColumnType("integer") + .HasColumnName("minumum_required_equipment_slots_matching_theme"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.PrimitiveCollection>("RequiredEquipmentSlotsMatchingTheme") + .IsRequired() + .HasColumnType("theme_equipment_slot[]") + .HasColumnName("required_equipment_slots_matching_theme"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_theme_events"); + + b.HasIndex("EventThemeId") + .HasDatabaseName("ix_theme_events_event_theme_id"); + + b.HasIndex("Name") + .HasDatabaseName("ix_theme_events_name"); + + b.ToTable("theme_events", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveCharacterId") + .HasColumnType("integer") + .HasColumnName("active_character_id"); + + b.Property("Avatar") + .HasColumnType("text") + .HasColumnName("avatar"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExperienceMultiplier") + .HasColumnType("real") + .HasColumnName("experience_multiplier"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("HeirloomPoints") + .HasColumnType("integer") + .HasColumnName("heirloom_points"); + + b.Property("IsDonor") + .HasColumnType("boolean") + .HasColumnName("is_donor"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Platform") + .HasColumnType("platform") + .HasColumnName("platform"); + + b.Property("PlatformUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("platform_user_id"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("Role") + .HasColumnType("role") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_users"); + + b.HasIndex("ActiveCharacterId") + .IsUnique() + .HasDatabaseName("ix_users_active_character_id"); + + b.HasIndex("Platform", "PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_users_platform_platform_user_id"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("BattleParticipantStatistic", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany() + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participant_statistic_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleParticipant", "Participant") + .WithOne("Statistic") + .HasForeignKey("BattleParticipantStatistic", "ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participant_statistic_battle_participants_participan"); + + b.Navigation("Battle"); + + b.Navigation("Participant"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_activity_logs_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => + { + b.HasOne("Crpg.Domain.Entities.ActivityLogs.ActivityLog", null) + .WithMany("Metadata") + .HasForeignKey("ActivityLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_activity_log_metadata_activity_logs_activity_log_id"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("Fighters") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighters_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .HasConstraintName("fk_battle_fighters_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") + .WithMany() + .HasForeignKey("SettlementId") + .HasConstraintName("fk_battle_fighters_settlements_settlement_id"); + + b.Navigation("Battle"); + + b.Navigation("Party"); + + b.Navigation("Settlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("FighterApplications") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighter_applications_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighter_applications_parties_party_id"); + + b.Navigation("Battle"); + + b.Navigation("Party"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("MercenaryApplications") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_mercenary_applications_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_mercenary_applications_characters_character_id"); + + b.Navigation("Battle"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("Participants") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleFighter", "CaptainFighter") + .WithMany() + .HasForeignKey("CaptainFighterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_battle_fighters_captain_fighter_id"); + + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_characters_character_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", "MercenaryApplication") + .WithMany() + .HasForeignKey("MercenaryApplicationId") + .HasConstraintName("fk_battle_participants_battle_mercenary_applications_mercenary"); + + b.Navigation("Battle"); + + b.Navigation("CaptainFighter"); + + b.Navigation("Character"); + + b.Navigation("MercenaryApplication"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("SideBriefings") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_side_briefings_battles_battle_id"); + + b.Navigation("Battle"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Characters") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_characters_users_user_id"); + + b.OwnsOne("Crpg.Domain.Entities.Characters.CharacterCharacteristics", "Characteristics", b1 => + { + b1.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b1.HasKey("CharacterId"); + + b1.ToTable("characters"); + + b1.WithOwner() + .HasForeignKey("CharacterId") + .HasConstraintName("fk_characters_characters_id"); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterAttributes", "Attributes", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Agility") + .HasColumnType("integer") + .HasColumnName("agility"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("attribute_points"); + + b2.Property("Strength") + .HasColumnType("integer") + .HasColumnName("strength"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterSkills", "Skills", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Athletics") + .HasColumnType("integer") + .HasColumnName("athletics"); + + b2.Property("IronFlesh") + .HasColumnType("integer") + .HasColumnName("iron_flesh"); + + b2.Property("MountedArchery") + .HasColumnType("integer") + .HasColumnName("mounted_archery"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("skill_points"); + + b2.Property("PowerDraw") + .HasColumnType("integer") + .HasColumnName("power_draw"); + + b2.Property("PowerStrike") + .HasColumnType("integer") + .HasColumnName("power_strike"); + + b2.Property("PowerThrow") + .HasColumnType("integer") + .HasColumnName("power_throw"); + + b2.Property("Riding") + .HasColumnType("integer") + .HasColumnName("riding"); + + b2.Property("Shield") + .HasColumnType("integer") + .HasColumnName("shield"); + + b2.Property("WeaponMaster") + .HasColumnType("integer") + .HasColumnName("weapon_master"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterWeaponProficiencies", "WeaponProficiencies", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Bow") + .HasColumnType("integer") + .HasColumnName("bow"); + + b2.Property("Crossbow") + .HasColumnType("integer") + .HasColumnName("crossbow"); + + b2.Property("OneHanded") + .HasColumnType("integer") + .HasColumnName("one_handed"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("weapon_proficiency_points"); + + b2.Property("Polearm") + .HasColumnType("integer") + .HasColumnName("polearm"); + + b2.Property("Throwing") + .HasColumnType("integer") + .HasColumnName("throwing"); + + b2.Property("TwoHanded") + .HasColumnType("integer") + .HasColumnName("two_handed"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.Navigation("Attributes") + .IsRequired(); + + b1.Navigation("Skills") + .IsRequired(); + + b1.Navigation("WeaponProficiencies") + .IsRequired(); + }); + + b.OwnsMany("Crpg.Domain.Entities.Characters.CharacterStatistics", "Statistics", b1 => + { + b1.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Assists") + .HasColumnType("integer") + .HasColumnName("assists"); + + b1.Property("Deaths") + .HasColumnType("integer") + .HasColumnName("deaths"); + + b1.Property("GameMode") + .HasColumnType("game_mode") + .HasColumnName("game_mode"); + + b1.Property("Kills") + .HasColumnType("integer") + .HasColumnName("kills"); + + b1.Property("PlayTime") + .HasColumnType("interval") + .HasColumnName("play_time"); + + b1.HasKey("CharacterId", "Id") + .HasName("pk_character_statistics"); + + b1.ToTable("character_statistics", (string)null); + + b1.WithOwner("Character") + .HasForeignKey("CharacterId") + .HasConstraintName("fk_character_statistics_characters_character_id"); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterRating", "Rating", b2 => + { + b2.Property("CharacterStatisticsCharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b2.Property("CharacterStatisticsId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("CompetitiveValue") + .HasColumnType("real") + .HasColumnName("competitive_rating"); + + b2.Property("Deviation") + .HasColumnType("real") + .HasColumnName("rating_deviation"); + + b2.Property("Value") + .HasColumnType("real") + .HasColumnName("rating"); + + b2.Property("Volatility") + .HasColumnType("real") + .HasColumnName("rating_volatility"); + + b2.HasKey("CharacterStatisticsCharacterId", "CharacterStatisticsId"); + + b2.ToTable("character_statistics"); + + b2.WithOwner() + .HasForeignKey("CharacterStatisticsCharacterId", "CharacterStatisticsId") + .HasConstraintName("fk_character_statistics_character_statistics_character_id_id"); + }); + + b1.Navigation("Character"); + + b1.Navigation("Rating") + .IsRequired(); + }); + + b.Navigation("Characteristics") + .IsRequired(); + + b.Navigation("Statistics"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("ArmoryBorrowedItems") + .HasForeignKey("BorrowerClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clans_borrower_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Borrower") + .WithMany("ArmoryBorrowedItems") + .HasForeignKey("BorrowerUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clan_members_borrower_user_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("ClanArmoryBorrowedItem") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_user_items_user_item_id"); + + b.HasOne("Crpg.Domain.Entities.Items.ClanArmoryItem", "ArmoryItem") + .WithOne("BorrowedItem") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clan_armory_items_user_item_id"); + + b.Navigation("ArmoryItem"); + + b.Navigation("Borrower"); + + b.Navigation("Clan"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("Invitations") + .HasForeignKey("ClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_clans_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "Invitee") + .WithMany() + .HasForeignKey("InviteeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_users_invitee_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "Inviter") + .WithMany() + .HasForeignKey("InviterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_users_inviter_id"); + + b.Navigation("Clan"); + + b.Navigation("Invitee"); + + b.Navigation("Inviter"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("Members") + .HasForeignKey("ClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_members_clans_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithOne("ClanMembership") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanMember", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_members_users_user_id"); + + b.Navigation("Clan"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_game_events_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("ArmoryItems") + .HasForeignKey("LenderClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_clans_lender_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Lender") + .WithMany("ArmoryItems") + .HasForeignKey("LenderUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_clan_members_lender_user_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("ClanArmoryItem") + .HasForeignKey("Crpg.Domain.Entities.Items.ClanArmoryItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_user_items_user_item_id"); + + b.Navigation("Clan"); + + b.Navigation("Lender"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany("EquippedItems") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_equipped_items_characters_character_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithMany("EquippedItems") + .HasForeignKey("UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_equipped_items_user_items_user_item_id"); + + b.Navigation("Character"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "PrimaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("primary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("primary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("primary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("primary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("primary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("primary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("primary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("primary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("primary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("primary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("primary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("primary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("primary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("primary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("primary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("primary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "SecondaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("secondary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("secondary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("secondary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("secondary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("secondary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("secondary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("secondary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("secondary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("secondary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("secondary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("secondary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("secondary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("secondary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "TertiaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("tertiary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("tertiary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("tertiary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("tertiary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("tertiary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("tertiary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tertiary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("tertiary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("tertiary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("tertiary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("tertiary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("tertiary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("tertiary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemArmorComponent", "Armor", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("ArmArmor") + .HasColumnType("integer") + .HasColumnName("armor_arm"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("armor_body"); + + b1.Property("FamilyType") + .HasColumnType("integer") + .HasColumnName("armor_family_type"); + + b1.Property("HeadArmor") + .HasColumnType("integer") + .HasColumnName("armor_head"); + + b1.Property("LegArmor") + .HasColumnType("integer") + .HasColumnName("armor_leg"); + + b1.Property("MaterialType") + .HasColumnType("integer") + .HasColumnName("armor_material_type"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemMountComponent", "Mount", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("BodyLength") + .HasColumnType("integer") + .HasColumnName("mount_body_length"); + + b1.Property("ChargeDamage") + .HasColumnType("integer") + .HasColumnName("mount_charge_damage"); + + b1.Property("FamilyType") + .HasColumnType("integer") + .HasColumnName("mount_family_type"); + + b1.Property("HitPoints") + .HasColumnType("integer") + .HasColumnName("mount_hit_points"); + + b1.Property("Maneuver") + .HasColumnType("integer") + .HasColumnName("mount_maneuver"); + + b1.Property("Speed") + .HasColumnType("integer") + .HasColumnName("mount_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.Navigation("Armor"); + + b.Navigation("Mount"); + + b.Navigation("PrimaryWeapon"); + + b.Navigation("SecondaryWeapon"); + + b.Navigation("TertiaryWeapon"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_stacks_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany("Items") + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.PartyTransferOffer", "PartyTransferOffer") + .WithMany("Items") + .HasForeignKey("PartyTransferOfferId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_party_transfer_offers_party_transfer_offer_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") + .WithMany("Items") + .HasForeignKey("SettlementId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_settlements_settlement_id"); + + b.Navigation("Item"); + + b.Navigation("Party"); + + b.Navigation("PartyTransferOffer"); + + b.Navigation("Settlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => + { + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("PersonalItem") + .HasForeignKey("Crpg.Domain.Entities.Items.PersonalItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_personal_items_user_items_user_item_id"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany("UserItems") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_items_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Items") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_items_users_user_id"); + + b.Navigation("Item"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("ItemPresets") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_item_presets_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_user_item_preset_slots_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItemPreset", "UserItemPreset") + .WithMany("Slots") + .HasForeignKey("UserItemPresetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_item_preset_slots_user_item_presets_user_item_preset_id"); + + b.Navigation("Item"); + + b.Navigation("UserItemPreset"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithOne("Limitations") + .HasForeignKey("Crpg.Domain.Entities.Limitations.CharacterLimitations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_character_limitations_characters_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "Seller") + .WithMany("MarketplaceListings") + .HasForeignKey("SellerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_marketplace_listings_users_seller_id"); + + b.Navigation("Seller"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .HasConstraintName("fk_marketplace_listing_assets_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Marketplace.MarketplaceListing", "MarketplaceListing") + .WithMany("Assets") + .HasForeignKey("MarketplaceListingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_marketplace_listing_assets_marketplace_listings_marketplace"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithMany("MarketplaceListingAssets") + .HasForeignKey("UserItemId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_marketplace_listing_assets_user_items_user_item_id"); + + b.Navigation("Item"); + + b.Navigation("MarketplaceListing"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Notifications") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_notifications_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => + { + b.HasOne("Crpg.Domain.Entities.Notifications.UserNotification", null) + .WithMany("Metadata") + .HasForeignKey("UserNotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_notification_metadata_user_notifications_user_notifica"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "CurrentBattle") + .WithMany() + .HasForeignKey("CurrentBattleId") + .HasConstraintName("fk_parties_battles_current_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "CurrentParty") + .WithMany() + .HasForeignKey("CurrentPartyId") + .HasConstraintName("fk_parties_parties_current_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "CurrentSettlement") + .WithMany() + .HasForeignKey("CurrentSettlementId") + .HasConstraintName("fk_parties_settlements_current_settlement_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithOne("Party") + .HasForeignKey("Crpg.Domain.Entities.Parties.Party", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_parties_users_id"); + + b.Navigation("CurrentBattle"); + + b.Navigation("CurrentParty"); + + b.Navigation("CurrentSettlement"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany("Orders") + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_orders_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "TargetedBattle") + .WithMany() + .HasForeignKey("TargetedBattleId") + .HasConstraintName("fk_party_orders_battles_targeted_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetedParty") + .WithMany() + .HasForeignKey("TargetedPartyId") + .HasConstraintName("fk_party_orders_parties_targeted_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "TargetedSettlement") + .WithMany() + .HasForeignKey("TargetedSettlementId") + .HasConstraintName("fk_party_orders_settlements_targeted_settlement_id"); + + b.Navigation("Party"); + + b.Navigation("TargetedBattle"); + + b.Navigation("TargetedParty"); + + b.Navigation("TargetedSettlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_transfer_offers_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetParty") + .WithMany() + .HasForeignKey("TargetPartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_transfer_offers_parties_target_party_id"); + + b.Navigation("Party"); + + b.Navigation("TargetParty"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => + { + b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") + .WithMany() + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_user_quests_quest_definitions_quest_definition_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_quests_users_user_id"); + + b.Navigation("QuestDefinition"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => + { + b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") + .WithMany() + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_weekly_quest_assignments_quest_definitions_quest_definition"); + + b.Navigation("QuestDefinition"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedByUser") + .WithMany() + .HasForeignKey("RestrictedByUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_restrictions_users_restricted_by_user_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedUser") + .WithMany("Restrictions") + .HasForeignKey("RestrictedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_restrictions_users_restricted_user_id"); + + b.Navigation("RestrictedByUser"); + + b.Navigation("RestrictedUser"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Owner") + .WithMany("OwnedSettlements") + .HasForeignKey("OwnerId") + .HasConstraintName("fk_settlements_parties_owner_id"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.ThemeEvent", b => + { + b.HasOne("Crpg.Domain.Entities.Themes.Theme", "EventTheme") + .WithMany() + .HasForeignKey("EventThemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_theme_events_themes_event_theme_id"); + + b.Navigation("EventTheme"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "ActiveCharacter") + .WithOne() + .HasForeignKey("Crpg.Domain.Entities.Users.User", "ActiveCharacterId") + .HasConstraintName("fk_users_characters_active_character_id"); + + b.Navigation("ActiveCharacter"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.Navigation("Metadata"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => + { + b.Navigation("FighterApplications"); + + b.Navigation("Fighters"); + + b.Navigation("MercenaryApplications"); + + b.Navigation("Participants"); + + b.Navigation("SideBriefings"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.Navigation("Statistic"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.Navigation("EquippedItems"); + + b.Navigation("Limitations"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => + { + b.Navigation("ArmoryBorrowedItems"); + + b.Navigation("ArmoryItems"); + + b.Navigation("Invitations"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.Navigation("ArmoryBorrowedItems"); + + b.Navigation("ArmoryItems"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.Navigation("BorrowedItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.Navigation("UserItems"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.Navigation("ClanArmoryBorrowedItem"); + + b.Navigation("ClanArmoryItem"); + + b.Navigation("EquippedItems"); + + b.Navigation("MarketplaceListingAssets"); + + b.Navigation("PersonalItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.Navigation("Slots"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.Navigation("Assets"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.Navigation("Metadata"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + + b.Navigation("OwnedSettlements"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.Navigation("Characters"); + + b.Navigation("ClanMembership"); + + b.Navigation("ItemPresets"); + + b.Navigation("Items"); + + b.Navigation("MarketplaceListings"); + + b.Navigation("Notifications"); + + b.Navigation("Party"); + + b.Navigation("Restrictions"); + }); +#pragma warning restore 612, 618 + } + } +} From 8fa0cac437a2dac3099ce2296df5095a51bf8d96 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 19:20:20 +0200 Subject: [PATCH 02/38] Adds ability to get themes --- .../Themes/Models/ThemeViewModel.cs | 11 +++++ .../Themes/Queries/GetThemesQuery.cs | 22 +++++++++ src/WebApi/Controllers/ThemesController.cs | 18 +++++++ .../Themes/GetThemesQueryTest.cs | 48 +++++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 src/Application/Themes/Models/ThemeViewModel.cs create mode 100644 src/Application/Themes/Queries/GetThemesQuery.cs create mode 100644 src/WebApi/Controllers/ThemesController.cs create mode 100644 test/Application.UTest/Themes/GetThemesQueryTest.cs diff --git a/src/Application/Themes/Models/ThemeViewModel.cs b/src/Application/Themes/Models/ThemeViewModel.cs new file mode 100644 index 000000000..b931dca14 --- /dev/null +++ b/src/Application/Themes/Models/ThemeViewModel.cs @@ -0,0 +1,11 @@ +using Crpg.Application.Common.Mappings; +using Crpg.Domain.Entities.Themes; + +namespace Crpg.Application.Themes.Models; + +public class ThemeViewModel : IMapFrom +{ + public int Id { get; set; } + + public string Name { get; set; } = default!; +} diff --git a/src/Application/Themes/Queries/GetThemesQuery.cs b/src/Application/Themes/Queries/GetThemesQuery.cs new file mode 100644 index 000000000..57bd8b8ca --- /dev/null +++ b/src/Application/Themes/Queries/GetThemesQuery.cs @@ -0,0 +1,22 @@ +using AutoMapper; +using Crpg.Application.Common.Interfaces; +using Crpg.Application.Common.Mediator; +using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Models; +using Microsoft.EntityFrameworkCore; + +namespace Crpg.Application.Themes.Queries; + +public class GetThemesQuery : IMediatorRequest> +{ + internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler> + { + public async ValueTask>> Handle(GetThemesQuery req, CancellationToken cancellationToken) + { + var themes = await db.Themes.AsNoTracking().ToListAsync(cancellationToken); + var viewModels = mapper.Map>(themes); + + return new(viewModels); + } + } +} diff --git a/src/WebApi/Controllers/ThemesController.cs b/src/WebApi/Controllers/ThemesController.cs new file mode 100644 index 000000000..4bfa60db3 --- /dev/null +++ b/src/WebApi/Controllers/ThemesController.cs @@ -0,0 +1,18 @@ +using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Models; +using Crpg.Application.Themes.Queries; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Crpg.WebApi.Controllers; + +[Authorize(Policy = UserPolicy)] +public class ThemesController : BaseController +{ + /// + /// Gets all themes. + /// + /// Ok. + [HttpGet] + public Task>>> GetThemes() => ResultToActionAsync(Mediator.Send(new GetThemesQuery())); +} diff --git a/test/Application.UTest/Themes/GetThemesQueryTest.cs b/test/Application.UTest/Themes/GetThemesQueryTest.cs new file mode 100644 index 000000000..2a9e91134 --- /dev/null +++ b/test/Application.UTest/Themes/GetThemesQueryTest.cs @@ -0,0 +1,48 @@ +using Crpg.Application.Themes.Queries; +using Crpg.Domain.Entities.Themes; +using NUnit.Framework; + +namespace Crpg.Application.UTest.Themes; + +public class GetThemesQueryTest : TestBase +{ + [Test] + public async Task ShouldReturnEmptyWhenNoThemes() + { + var handler = new GetThemesQuery.Handler(ActDb, Mapper); + var result = await handler.Handle(new GetThemesQuery(), CancellationToken.None); + + Assert.That(result?.Data, Is.Empty); + } + + [Test] + public async Task ShouldReturnThemes() + { + var themeOne = CreateDefaultTheme(name: "Theme 1"); + var themeTwo = CreateDefaultTheme(name: "Theme 2"); + ArrangeDb.Themes.AddRange(themeOne, themeTwo); + await ArrangeDb.SaveChangesAsync(CancellationToken.None); + + var handler = new GetThemesQuery.Handler(ActDb, Mapper); + + var result = await handler.Handle(new GetThemesQuery(), CancellationToken.None); + + Assert.That(result, Is.Not.Null); + Assert.That(result.Errors, Is.Null); + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data, Has.Count.EqualTo(2)); + + var resultOne = result.Data!.Single(x => x.Name == themeOne.Name); + Assert.That(resultOne.Id, Is.GreaterThan(0)); + Assert.That(resultOne.Name, Is.EqualTo(themeOne.Name)); + + var resultTwo = result.Data!.Single(x => x.Name == themeTwo.Name); + Assert.That(resultTwo.Id, Is.GreaterThan(0)); + Assert.That(resultTwo.Name, Is.EqualTo(themeTwo.Name)); + } + + private static Theme CreateDefaultTheme(string name = "My Theme") + { + return new Theme(name); + } +} From c0bf667a20849719efb75228bd539060c7d2d250 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 19:24:28 +0200 Subject: [PATCH 03/38] Adds ability to create a theme --- .../Themes/Commands/CreateThemeCommand.cs | 37 ++++++++++ src/WebApi/Controllers/ThemesController.cs | 9 +++ .../Themes/CreateThemeCommandTest.cs | 67 +++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 src/Application/Themes/Commands/CreateThemeCommand.cs create mode 100644 test/Application.UTest/Themes/CreateThemeCommandTest.cs diff --git a/src/Application/Themes/Commands/CreateThemeCommand.cs b/src/Application/Themes/Commands/CreateThemeCommand.cs new file mode 100644 index 000000000..c10383e06 --- /dev/null +++ b/src/Application/Themes/Commands/CreateThemeCommand.cs @@ -0,0 +1,37 @@ +using AutoMapper; +using Crpg.Application.Common.Interfaces; +using Crpg.Application.Common.Mediator; +using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Models; +using Crpg.Domain.Entities.Themes; +using FluentValidation; + +namespace Crpg.Application.Themes.Commands; + +public record CreateThemeCommand : IMediatorRequest +{ + public string Name { get; set; } = default!; + + public class Validator : AbstractValidator + { + public Validator() + { + RuleFor(t => t.Name) + .NotEmpty().WithMessage("Theme name is required.") + .MaximumLength(100).WithMessage("Theme name cannot exceed 100 characters."); + } + } + + internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler + { + public async ValueTask> Handle(CreateThemeCommand req, CancellationToken cancellationToken) + { + var themeToAdd = new Theme(req.Name); + + db.Themes.Add(themeToAdd); + await db.SaveChangesAsync(cancellationToken); + + return new(mapper.Map(themeToAdd)); + } + } +} diff --git a/src/WebApi/Controllers/ThemesController.cs b/src/WebApi/Controllers/ThemesController.cs index 4bfa60db3..94d030fbe 100644 --- a/src/WebApi/Controllers/ThemesController.cs +++ b/src/WebApi/Controllers/ThemesController.cs @@ -1,4 +1,5 @@ using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Commands; using Crpg.Application.Themes.Models; using Crpg.Application.Themes.Queries; using Microsoft.AspNetCore.Authorization; @@ -15,4 +16,12 @@ public class ThemesController : BaseController /// Ok. [HttpGet] public Task>>> GetThemes() => ResultToActionAsync(Mediator.Send(new GetThemesQuery())); + + /// + /// Creates a new theme. + /// + /// Ok. + [HttpPost] + [Authorize(Policy = AdminPolicy)] + public Task>> CreateTheme([FromBody] CreateThemeCommand req) => ResultToActionAsync(Mediator.Send(req)); } diff --git a/test/Application.UTest/Themes/CreateThemeCommandTest.cs b/test/Application.UTest/Themes/CreateThemeCommandTest.cs new file mode 100644 index 000000000..bd6292f3f --- /dev/null +++ b/test/Application.UTest/Themes/CreateThemeCommandTest.cs @@ -0,0 +1,67 @@ +using Crpg.Application.Themes.Commands; +using NUnit.Framework; + +namespace Crpg.Application.UTest.Themes; + +public class CreateThemeCommandTest : TestBase +{ + [Test] + public async Task ShouldCreateTheme() + { + var handler = new CreateThemeCommand.Handler(ActDb, Mapper); + var command = new CreateThemeCommand + { + Name = "Test Theme", + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data!.Name, Is.EqualTo(command.Name)); + } + + [Test] + public void ShouldFailValidationWhenNameIsEmpty() + { + var validator = new CreateThemeCommand.Validator(); + var command = new CreateThemeCommand + { + Name = string.Empty, }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors, Has.Count.GreaterThan(0)); + Assert.That(result.Errors[0].PropertyName, Is.EqualTo("Name")); + } + + [Test] + public void ShouldFailValidationWhenNameExceeds100Characters() + { + var validator = new CreateThemeCommand.Validator(); + var command = new CreateThemeCommand + { + Name = new string('a', 101), + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "Name"), Is.True); + } + + [Test] + public async Task ShouldReturnThemeWithId() + { + var handler = new CreateThemeCommand.Handler(ActDb, Mapper); + var command = new CreateThemeCommand + { + Name = "Theme With ID", + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data!.Id, Is.GreaterThan(0)); + } +} From c9110c86efd7e467589276b1c57d274ce0e16d9d Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 19:36:18 +0200 Subject: [PATCH 04/38] Adds ability to get theme events --- .../Themes/Models/ThemeEventViewModel.cs | 49 +++++++++++++ .../Themes/Queries/GetThemeEventsQuery.cs | 22 ++++++ src/Domain/Entities/Themes/ThemeEvent.cs | 2 + src/WebApi/Controllers/ThemesController.cs | 7 ++ .../Themes/GetThemeEventsQueryTest.cs | 71 +++++++++++++++++++ 5 files changed, 151 insertions(+) create mode 100644 src/Application/Themes/Models/ThemeEventViewModel.cs create mode 100644 src/Application/Themes/Queries/GetThemeEventsQuery.cs create mode 100644 test/Application.UTest/Themes/GetThemeEventsQueryTest.cs diff --git a/src/Application/Themes/Models/ThemeEventViewModel.cs b/src/Application/Themes/Models/ThemeEventViewModel.cs new file mode 100644 index 000000000..6959422c9 --- /dev/null +++ b/src/Application/Themes/Models/ThemeEventViewModel.cs @@ -0,0 +1,49 @@ +using Crpg.Application.Common.Mappings; +using Crpg.Domain.Entities.Themes; + +namespace Crpg.Application.Themes.Models; + +public class ThemeEventViewModel : IMapFrom +{ + public int Id { get; set; } + + /// + /// The name of the event. + /// + public string Name { get; set; } = default!; + + /// + /// The gold multiplier to apply to the rewards earned with this theme. + /// + public float GoldMultiplier { get; set; } = 1.0f; + + /// + /// The experience multiplier to apply to the rewards earned with this theme. + /// + public float ExpMultiplier { get; set; } = 1.0f; + + /// + /// The time from which the theme is active. + /// + public DateTimeOffset ActiveFromUtc { get; set; } + + /// + /// The time where the theme stops being active. If null, the theme is active indefinitely. + /// + public DateTimeOffset? ActiveUntilUtc { get; set; } + + /// + /// The equipment slots that must contain items matching the events theme for the player to be eligible for the event rewards. + /// + public List RequiredEquipmentSlotsMatchingTheme { get; set; } = new(); + + /// + /// The minimum amount of equipment slots that must contain items matching the events theme for the player to be eligible for the event rewards. + /// + public int MinumumRequiredEquipmentSlotsMatchingTheme { get; set; } + + /// + /// The theme of the event. + /// + public Theme EventTheme { get; set; } = default!; +} diff --git a/src/Application/Themes/Queries/GetThemeEventsQuery.cs b/src/Application/Themes/Queries/GetThemeEventsQuery.cs new file mode 100644 index 000000000..babfa8a59 --- /dev/null +++ b/src/Application/Themes/Queries/GetThemeEventsQuery.cs @@ -0,0 +1,22 @@ +using AutoMapper; +using Crpg.Application.Common.Interfaces; +using Crpg.Application.Common.Mediator; +using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Models; +using Microsoft.EntityFrameworkCore; + +namespace Crpg.Application.Themes.Queries; + +public class GetThemeEventsQuery : IMediatorRequest> +{ + internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler> + { + public async ValueTask>> Handle(GetThemeEventsQuery req, CancellationToken cancellationToken) + { + var themes = await db.ThemeEvents.AsNoTracking().ToListAsync(cancellationToken); + var viewModels = mapper.Map>(themes); + + return new(viewModels); + } + } +} diff --git a/src/Domain/Entities/Themes/ThemeEvent.cs b/src/Domain/Entities/Themes/ThemeEvent.cs index 5c76a97a2..de1333527 100644 --- a/src/Domain/Entities/Themes/ThemeEvent.cs +++ b/src/Domain/Entities/Themes/ThemeEvent.cs @@ -11,6 +11,7 @@ public ThemeEvent( DateTimeOffset activeFromUtc, DateTimeOffset? activeUntilUtc, List requiredEquipmentSlotsMatchingTheme, + int minumumRequiredEquipmentSlotsMatchingTheme, Theme theme) { Name = name; @@ -19,6 +20,7 @@ public ThemeEvent( ActiveFromUtc = activeFromUtc; ActiveUntilUtc = activeUntilUtc; RequiredEquipmentSlotsMatchingTheme = requiredEquipmentSlotsMatchingTheme; + MinumumRequiredEquipmentSlotsMatchingTheme = minumumRequiredEquipmentSlotsMatchingTheme; EventTheme = theme; } diff --git a/src/WebApi/Controllers/ThemesController.cs b/src/WebApi/Controllers/ThemesController.cs index 94d030fbe..118bbd0df 100644 --- a/src/WebApi/Controllers/ThemesController.cs +++ b/src/WebApi/Controllers/ThemesController.cs @@ -24,4 +24,11 @@ public class ThemesController : BaseController [HttpPost] [Authorize(Policy = AdminPolicy)] public Task>> CreateTheme([FromBody] CreateThemeCommand req) => ResultToActionAsync(Mediator.Send(req)); + + /// + /// Gets all theme events. + /// + /// Ok. + [HttpGet] + public Task>>> GetThemeEvents() => ResultToActionAsync(Mediator.Send(new GetThemeEventsQuery())); } diff --git a/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs b/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs new file mode 100644 index 000000000..445944240 --- /dev/null +++ b/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs @@ -0,0 +1,71 @@ +using Crpg.Application.Themes.Queries; +using Crpg.Domain.Entities.Themes; +using NUnit.Framework; + +namespace Crpg.Application.UTest.Themes; + +public class GetThemeEventsQueryTest : TestBase +{ + [Test] + public async Task ShouldReturnEmptyWhenNoThemes() + { + var handler = new GetThemeEventsQuery.Handler(ActDb, Mapper); + var result = await handler.Handle(new GetThemeEventsQuery(), CancellationToken.None); + + Assert.That(result?.Data, Is.Empty); + } + + [Test] + public async Task ShouldReturnThemes() + { + var themeOne = CreateDefaultTheme(name: "Theme 1"); + var themeTwo = CreateDefaultTheme(name: "Theme 2"); + ArrangeDb.ThemeEvents.AddRange(themeOne, themeTwo); + await ArrangeDb.SaveChangesAsync(CancellationToken.None); + + var handler = new GetThemeEventsQuery.Handler(ActDb, Mapper); + + var result = await handler.Handle(new GetThemeEventsQuery(), CancellationToken.None); + + Assert.That(result, Is.Not.Null); + Assert.That(result.Errors, Is.Null); + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data, Has.Count.EqualTo(2)); + + var resultOne = result.Data!.Single(x => x.Name == themeOne.Name); + Assert.That(resultOne.Id, Is.GreaterThan(0)); + Assert.That(resultOne.Name, Is.EqualTo(themeOne.Name)); + Assert.That(resultOne.GoldMultiplier, Is.EqualTo(themeOne.GoldMultiplier)); + Assert.That(resultOne.ExpMultiplier, Is.EqualTo(themeOne.ExpMultiplier)); + Assert.That(resultOne.ActiveFromUtc, Is.EqualTo(themeOne.ActiveFromUtc)); + Assert.That(resultOne.ActiveUntilUtc, Is.EqualTo(themeOne.ActiveUntilUtc)); + + var resultTwo = result.Data!.Single(x => x.Name == themeTwo.Name); + Assert.That(resultTwo.Id, Is.GreaterThan(0)); + Assert.That(resultTwo.Name, Is.EqualTo(themeTwo.Name)); + Assert.That(resultTwo.GoldMultiplier, Is.EqualTo(themeTwo.GoldMultiplier)); + Assert.That(resultTwo.ExpMultiplier, Is.EqualTo(themeTwo.ExpMultiplier)); + Assert.That(resultTwo.ActiveFromUtc, Is.EqualTo(themeTwo.ActiveFromUtc)); + Assert.That(resultTwo.ActiveUntilUtc, Is.EqualTo(themeTwo.ActiveUntilUtc)); + } + + private static ThemeEvent CreateDefaultTheme( + string name = "My theme event", + float goldMultiplier = 1.5f, + float expMultiplier = 2.0f, + DateTimeOffset? activeFromUtc = null, + DateTimeOffset? activeUntilUtc = null, + List requiredEquipmentSlotsMatchingTheme = null!, + int minumumRequiredEquipmentSlotsMatchingTheme = 1) + { + return new ThemeEvent( + name: name, + goldMultiplier: goldMultiplier, + expMultiplier: expMultiplier, + activeFromUtc: activeFromUtc ?? DateTimeOffset.UtcNow.AddDays(-1), + activeUntilUtc: activeUntilUtc ?? DateTimeOffset.UtcNow.AddDays(1), + requiredEquipmentSlotsMatchingTheme: requiredEquipmentSlotsMatchingTheme ?? [], + minumumRequiredEquipmentSlotsMatchingTheme, + theme: new Theme("theme")); + } +} From d218fab4518088ca1ffae2c97442d42c6b72bf0c Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 19:51:24 +0200 Subject: [PATCH 05/38] Adds ability to get active theme events --- .../Queries/GetActiveThemeEventsQuery.cs | 26 ++++++ .../Themes/Queries/GetThemeEventsQuery.cs | 2 +- src/WebApi/Controllers/ThemesController.cs | 9 ++- .../Themes/GetActiveThemeEventsQueryTest.cs | 81 +++++++++++++++++++ .../Themes/GetThemeEventsQueryTest.cs | 40 +++++---- 5 files changed, 139 insertions(+), 19 deletions(-) create mode 100644 src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs create mode 100644 test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs diff --git a/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs b/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs new file mode 100644 index 000000000..447d2dcf3 --- /dev/null +++ b/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs @@ -0,0 +1,26 @@ +using AutoMapper; +using Crpg.Application.Common.Interfaces; +using Crpg.Application.Common.Mediator; +using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Models; +using Microsoft.EntityFrameworkCore; + +namespace Crpg.Application.Themes.Queries; + +public class GetActiveThemeEventsQuery : IMediatorRequest> +{ + internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler> + { + public async ValueTask>> Handle(GetActiveThemeEventsQuery req, CancellationToken cancellationToken) + { + var now = DateTime.UtcNow; + var activeThemes = await db.ThemeEvents.Include(x => x.EventTheme).Where(theme => now >= theme.ActiveFromUtc && (theme.ActiveUntilUtc == null || now <= theme.ActiveUntilUtc)) + .AsNoTracking() + .ToListAsync(cancellationToken); + + var viewModels = mapper.Map>(activeThemes); + + return new(viewModels); + } + } +} diff --git a/src/Application/Themes/Queries/GetThemeEventsQuery.cs b/src/Application/Themes/Queries/GetThemeEventsQuery.cs index babfa8a59..9f0b6ae2f 100644 --- a/src/Application/Themes/Queries/GetThemeEventsQuery.cs +++ b/src/Application/Themes/Queries/GetThemeEventsQuery.cs @@ -13,7 +13,7 @@ internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHand { public async ValueTask>> Handle(GetThemeEventsQuery req, CancellationToken cancellationToken) { - var themes = await db.ThemeEvents.AsNoTracking().ToListAsync(cancellationToken); + var themes = await db.ThemeEvents.Include(x => x.EventTheme).AsNoTracking().ToListAsync(cancellationToken); var viewModels = mapper.Map>(themes); return new(viewModels); diff --git a/src/WebApi/Controllers/ThemesController.cs b/src/WebApi/Controllers/ThemesController.cs index 118bbd0df..d4a02ae6e 100644 --- a/src/WebApi/Controllers/ThemesController.cs +++ b/src/WebApi/Controllers/ThemesController.cs @@ -29,6 +29,13 @@ public class ThemesController : BaseController /// Gets all theme events. /// /// Ok. - [HttpGet] + [HttpGet("events")] public Task>>> GetThemeEvents() => ResultToActionAsync(Mediator.Send(new GetThemeEventsQuery())); + + /// + /// Gets all active theme events. + /// + /// Ok. + [HttpGet("events/active")] + public Task>>> GetActiveThemeEvents() => ResultToActionAsync(Mediator.Send(new GetActiveThemeEventsQuery())); } diff --git a/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs b/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs new file mode 100644 index 000000000..fdb7039e6 --- /dev/null +++ b/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs @@ -0,0 +1,81 @@ +using Crpg.Application.Themes.Queries; +using Crpg.Domain.Entities.Themes; +using NUnit.Framework; + +namespace Crpg.Application.UTest.Themes; + +public class GetActiveThemeEventsQueryTest : TestBase +{ + [Test] + public async Task ShouldReturnEmptyWhenNoActiveThemeEvents() + { + var handler = new GetActiveThemeEventsQuery.Handler(ActDb, Mapper); + var result = await handler.Handle(new GetActiveThemeEventsQuery(), CancellationToken.None); + + Assert.That(result?.Data, Is.Empty); + } + + [Test] + public async Task ShouldReturnActiveThemeEvents() + { + var now = DateTimeOffset.UtcNow; + var eventActiveForALimitedTime = CreateDefaultTheme(name: "Theme active for a limited time", activeFromUtc: now.AddDays(-1), activeUntilUtc: now.AddDays(1)); + var eventActiveIndefinitely = CreateDefaultTheme(name: "theme active indefinitely", activeFromUtc: now.AddDays(-1)); + var eventThatHasntStartedYet = CreateDefaultTheme("Theme that hasn't started yet.", activeFromUtc: now.AddDays(10)); + var eventThatHasAlreadyEnded = CreateDefaultTheme("Theme that has already passed.", activeFromUtc: now.AddDays(-10), activeUntilUtc: now.AddDays(-5)); + + ArrangeDb.ThemeEvents.AddRange(eventActiveForALimitedTime, eventActiveIndefinitely, eventThatHasntStartedYet, eventThatHasAlreadyEnded); + await ArrangeDb.SaveChangesAsync(CancellationToken.None); + + var handler = new GetActiveThemeEventsQuery.Handler(ActDb, Mapper); + + var result = await handler.Handle(new GetActiveThemeEventsQuery(), CancellationToken.None); + + Assert.That(result, Is.Not.Null); + Assert.That(result.Errors, Is.Null); + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data, Has.Count.EqualTo(2)); + + var resultOne = result.Data!.Single(x => x.Name == eventActiveForALimitedTime.Name); + Assert.That(resultOne.Id, Is.GreaterThan(0)); + Assert.That(resultOne.Name, Is.EqualTo(eventActiveForALimitedTime.Name)); + Assert.That(resultOne.GoldMultiplier, Is.EqualTo(eventActiveForALimitedTime.GoldMultiplier)); + Assert.That(resultOne.ExpMultiplier, Is.EqualTo(eventActiveForALimitedTime.ExpMultiplier)); + Assert.That(resultOne.ActiveFromUtc, Is.EqualTo(eventActiveForALimitedTime.ActiveFromUtc)); + Assert.That(resultOne.ActiveUntilUtc, Is.EqualTo(eventActiveForALimitedTime.ActiveUntilUtc)); + Assert.That(resultOne.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(eventActiveForALimitedTime.RequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultOne.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(eventActiveForALimitedTime.MinumumRequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultOne.EventTheme, Is.EqualTo(eventActiveForALimitedTime.EventTheme).UsingPropertiesComparer()); + + var resultTwo = result.Data!.Single(x => x.Name == eventActiveIndefinitely.Name); + Assert.That(resultTwo.Id, Is.GreaterThan(0)); + Assert.That(resultTwo.Name, Is.EqualTo(eventActiveIndefinitely.Name)); + Assert.That(resultTwo.GoldMultiplier, Is.EqualTo(eventActiveIndefinitely.GoldMultiplier)); + Assert.That(resultTwo.ExpMultiplier, Is.EqualTo(eventActiveIndefinitely.ExpMultiplier)); + Assert.That(resultTwo.ActiveFromUtc, Is.EqualTo(eventActiveIndefinitely.ActiveFromUtc)); + Assert.That(resultTwo.ActiveUntilUtc, Is.EqualTo(eventActiveIndefinitely.ActiveUntilUtc)); + Assert.That(resultTwo.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(eventActiveIndefinitely.RequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultTwo.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(eventActiveIndefinitely.MinumumRequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultTwo.EventTheme, Is.EqualTo(eventActiveIndefinitely.EventTheme).UsingPropertiesComparer()); + } + + private static ThemeEvent CreateDefaultTheme( + string name = "My theme event", + float goldMultiplier = 1.5f, + float expMultiplier = 2.0f, + DateTimeOffset? activeFromUtc = null, + DateTimeOffset? activeUntilUtc = null, + List requiredEquipmentSlotsMatchingTheme = null!, + int minumumRequiredEquipmentSlotsMatchingTheme = 1) + { + return new ThemeEvent( + name: name, + goldMultiplier: goldMultiplier, + expMultiplier: expMultiplier, + activeFromUtc: activeFromUtc ?? DateTimeOffset.UtcNow.AddDays(-1), + activeUntilUtc: activeUntilUtc ?? DateTimeOffset.UtcNow.AddDays(1), + requiredEquipmentSlotsMatchingTheme: requiredEquipmentSlotsMatchingTheme ?? [], + minumumRequiredEquipmentSlotsMatchingTheme, + theme: new Theme("theme")); + } +} diff --git a/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs b/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs index 445944240..60e28818e 100644 --- a/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs +++ b/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs @@ -7,7 +7,7 @@ namespace Crpg.Application.UTest.Themes; public class GetThemeEventsQueryTest : TestBase { [Test] - public async Task ShouldReturnEmptyWhenNoThemes() + public async Task ShouldReturnEmptyWhenNoThemeEvents() { var handler = new GetThemeEventsQuery.Handler(ActDb, Mapper); var result = await handler.Handle(new GetThemeEventsQuery(), CancellationToken.None); @@ -16,11 +16,11 @@ public async Task ShouldReturnEmptyWhenNoThemes() } [Test] - public async Task ShouldReturnThemes() + public async Task ShouldReturnThemeEvents() { - var themeOne = CreateDefaultTheme(name: "Theme 1"); - var themeTwo = CreateDefaultTheme(name: "Theme 2"); - ArrangeDb.ThemeEvents.AddRange(themeOne, themeTwo); + var themeEventOne = CreateDefaultTheme(name: "Theme 1"); + var themeEventTwo = CreateDefaultTheme(name: "Theme 2"); + ArrangeDb.ThemeEvents.AddRange(themeEventOne, themeEventTwo); await ArrangeDb.SaveChangesAsync(CancellationToken.None); var handler = new GetThemeEventsQuery.Handler(ActDb, Mapper); @@ -32,21 +32,27 @@ public async Task ShouldReturnThemes() Assert.That(result.Data, Is.Not.Null); Assert.That(result.Data, Has.Count.EqualTo(2)); - var resultOne = result.Data!.Single(x => x.Name == themeOne.Name); + var resultOne = result.Data!.Single(x => x.Name == themeEventOne.Name); Assert.That(resultOne.Id, Is.GreaterThan(0)); - Assert.That(resultOne.Name, Is.EqualTo(themeOne.Name)); - Assert.That(resultOne.GoldMultiplier, Is.EqualTo(themeOne.GoldMultiplier)); - Assert.That(resultOne.ExpMultiplier, Is.EqualTo(themeOne.ExpMultiplier)); - Assert.That(resultOne.ActiveFromUtc, Is.EqualTo(themeOne.ActiveFromUtc)); - Assert.That(resultOne.ActiveUntilUtc, Is.EqualTo(themeOne.ActiveUntilUtc)); + Assert.That(resultOne.Name, Is.EqualTo(themeEventOne.Name)); + Assert.That(resultOne.GoldMultiplier, Is.EqualTo(themeEventOne.GoldMultiplier)); + Assert.That(resultOne.ExpMultiplier, Is.EqualTo(themeEventOne.ExpMultiplier)); + Assert.That(resultOne.ActiveFromUtc, Is.EqualTo(themeEventOne.ActiveFromUtc)); + Assert.That(resultOne.ActiveUntilUtc, Is.EqualTo(themeEventOne.ActiveUntilUtc)); + Assert.That(resultOne.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(themeEventOne.RequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultOne.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(themeEventOne.MinumumRequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultOne.EventTheme, Is.EqualTo(themeEventOne.EventTheme).UsingPropertiesComparer()); - var resultTwo = result.Data!.Single(x => x.Name == themeTwo.Name); + var resultTwo = result.Data!.Single(x => x.Name == themeEventTwo.Name); Assert.That(resultTwo.Id, Is.GreaterThan(0)); - Assert.That(resultTwo.Name, Is.EqualTo(themeTwo.Name)); - Assert.That(resultTwo.GoldMultiplier, Is.EqualTo(themeTwo.GoldMultiplier)); - Assert.That(resultTwo.ExpMultiplier, Is.EqualTo(themeTwo.ExpMultiplier)); - Assert.That(resultTwo.ActiveFromUtc, Is.EqualTo(themeTwo.ActiveFromUtc)); - Assert.That(resultTwo.ActiveUntilUtc, Is.EqualTo(themeTwo.ActiveUntilUtc)); + Assert.That(resultTwo.Name, Is.EqualTo(themeEventTwo.Name)); + Assert.That(resultTwo.GoldMultiplier, Is.EqualTo(themeEventTwo.GoldMultiplier)); + Assert.That(resultTwo.ExpMultiplier, Is.EqualTo(themeEventTwo.ExpMultiplier)); + Assert.That(resultTwo.ActiveFromUtc, Is.EqualTo(themeEventTwo.ActiveFromUtc)); + Assert.That(resultTwo.ActiveUntilUtc, Is.EqualTo(themeEventTwo.ActiveUntilUtc)); + Assert.That(resultTwo.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(themeEventTwo.RequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultTwo.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(themeEventTwo.MinumumRequiredEquipmentSlotsMatchingTheme)); + Assert.That(resultTwo.EventTheme, Is.EqualTo(themeEventTwo.EventTheme).UsingPropertiesComparer()); } private static ThemeEvent CreateDefaultTheme( From d957abfb99f4403ebcd98a13a017379c3593c52e Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 20:21:48 +0200 Subject: [PATCH 06/38] Adds ability to create theme event --- .../Common/Results/CommonErrors.cs | 6 + src/Application/Common/Results/ErrorCode.cs | 1 + .../Themes/Commands/CreateThemeCommand.cs | 2 +- .../Commands/CreateThemeEventCommand.cs | 80 +++++ src/WebApi/Controllers/ThemesController.cs | 8 + .../Themes/CreateThemeEventCommandTest.cs | 311 ++++++++++++++++++ 6 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 src/Application/Themes/Commands/CreateThemeEventCommand.cs create mode 100644 test/Application.UTest/Themes/CreateThemeEventCommandTest.cs diff --git a/src/Application/Common/Results/CommonErrors.cs b/src/Application/Common/Results/CommonErrors.cs index bfaa0c0d9..d592745d7 100644 --- a/src/Application/Common/Results/CommonErrors.cs +++ b/src/Application/Common/Results/CommonErrors.cs @@ -568,5 +568,11 @@ public static Error UserItemMaxRankReached(int userItemId, int maxRank) => { Title = "Quest not completed", Detail = $"Quest with id '{userQuestId}' requires {requiredValue} but current progress is {currentValue}", + }; + + public static Error ThemeNotFound(int themeId) => new(ErrorType.NotFound, ErrorCode.ThemeNotFound) + { + Title = "Theme not found", + Detail = $"Theme with id '{themeId}' could not be found.", }; } diff --git a/src/Application/Common/Results/ErrorCode.cs b/src/Application/Common/Results/ErrorCode.cs index ffee7b1a7..4848d401d 100644 --- a/src/Application/Common/Results/ErrorCode.cs +++ b/src/Application/Common/Results/ErrorCode.cs @@ -100,4 +100,5 @@ public enum ErrorCode QuestExpired, QuestDefinitionNotFound, QuestNotCompleted, + ThemeNotFound, } diff --git a/src/Application/Themes/Commands/CreateThemeCommand.cs b/src/Application/Themes/Commands/CreateThemeCommand.cs index c10383e06..9f9829fe4 100644 --- a/src/Application/Themes/Commands/CreateThemeCommand.cs +++ b/src/Application/Themes/Commands/CreateThemeCommand.cs @@ -28,7 +28,7 @@ public async ValueTask> Handle(CreateThemeCommand req, Ca { var themeToAdd = new Theme(req.Name); - db.Themes.Add(themeToAdd); + await db.Themes.AddAsync(themeToAdd); await db.SaveChangesAsync(cancellationToken); return new(mapper.Map(themeToAdd)); diff --git a/src/Application/Themes/Commands/CreateThemeEventCommand.cs b/src/Application/Themes/Commands/CreateThemeEventCommand.cs new file mode 100644 index 000000000..0aac91f31 --- /dev/null +++ b/src/Application/Themes/Commands/CreateThemeEventCommand.cs @@ -0,0 +1,80 @@ +using AutoMapper; +using Crpg.Application.Common.Interfaces; +using Crpg.Application.Common.Mediator; +using Crpg.Application.Common.Results; +using Crpg.Application.Themes.Models; +using Crpg.Domain.Entities.Themes; +using FluentValidation; + +namespace Crpg.Application.Themes.Commands; + +public record CreateThemeEventCommand : IMediatorRequest +{ + + public string Name { get; set; } = default!; + + public float GoldMultiplier { get; set; } = 1.0f; + + public float ExpMultiplier { get; set; } = 1.0f; + + public DateTimeOffset ActiveFromUtc { get; set; } + + public DateTimeOffset? ActiveUntilUtc { get; set; } + + public List RequiredEquipmentSlotsMatchingTheme { get; set; } = new(); + + public int MinumumRequiredEquipmentSlotsMatchingTheme { get; set; } + + public int ThemeId { get; set; } = default!; + + public class Validator : AbstractValidator + { + public Validator() + { + RuleFor(t => t.Name) + .NotEmpty().WithMessage("Theme name is required.") + .MaximumLength(100).WithMessage("Theme name cannot exceed 100 characters."); + + RuleFor(r => r.GoldMultiplier).GreaterThan(0); + RuleFor(r => r.ExpMultiplier).GreaterThan(0); + + RuleFor(r => r.ActiveFromUtc) + .NotEmpty() + .Must(dt => dt.Offset == TimeSpan.Zero) + .WithMessage("ActiveFromUtc must be UTC."); + + RuleFor(r => r.ActiveUntilUtc) + .Must(dt => dt == null || dt.Value.Offset == TimeSpan.Zero) + .WithMessage("ActiveUntilUtc must be UTC.") + .Must((cmd, until) => until == null || until > cmd.ActiveFromUtc) + .WithMessage("ActiveUntilUtc must be after ActiveFromUtc."); + } + } + + internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler + { + public async ValueTask> Handle(CreateThemeEventCommand req, CancellationToken cancellationToken) + { + var theme = await db.Themes.FindAsync([req.ThemeId], cancellationToken: cancellationToken); + if (theme is null) + { + return new(CommonErrors.ThemeNotFound(req.ThemeId)); + } + + var themeEventToAdd = new ThemeEvent( + name: req.Name, + goldMultiplier: req.GoldMultiplier, + expMultiplier: req.ExpMultiplier, + activeFromUtc: req.ActiveFromUtc, + activeUntilUtc: req.ActiveUntilUtc, + requiredEquipmentSlotsMatchingTheme: req.RequiredEquipmentSlotsMatchingTheme, + minumumRequiredEquipmentSlotsMatchingTheme: req.MinumumRequiredEquipmentSlotsMatchingTheme, + theme: theme); + + await db.ThemeEvents.AddAsync(themeEventToAdd); + await db.SaveChangesAsync(cancellationToken); + + return new(mapper.Map(themeEventToAdd)); + } + } +} diff --git a/src/WebApi/Controllers/ThemesController.cs b/src/WebApi/Controllers/ThemesController.cs index d4a02ae6e..7257a0a5b 100644 --- a/src/WebApi/Controllers/ThemesController.cs +++ b/src/WebApi/Controllers/ThemesController.cs @@ -38,4 +38,12 @@ public class ThemesController : BaseController /// Ok. [HttpGet("events/active")] public Task>>> GetActiveThemeEvents() => ResultToActionAsync(Mediator.Send(new GetActiveThemeEventsQuery())); + + /// + /// Creates a new theme event. + /// + /// Ok. + [HttpPost("events")] + [Authorize(Policy = AdminPolicy)] + public Task>> CreateThemeEvent([FromBody] CreateThemeEventCommand req) => ResultToActionAsync(Mediator.Send(req)); } diff --git a/test/Application.UTest/Themes/CreateThemeEventCommandTest.cs b/test/Application.UTest/Themes/CreateThemeEventCommandTest.cs new file mode 100644 index 000000000..2233aeef2 --- /dev/null +++ b/test/Application.UTest/Themes/CreateThemeEventCommandTest.cs @@ -0,0 +1,311 @@ +using Crpg.Application.Themes.Commands; +using Crpg.Domain.Entities.Themes; +using NUnit.Framework; + +namespace Crpg.Application.UTest.Themes; + +public class CreateThemeEventCommandTest : TestBase +{ + [Test] + public async Task ShouldCreateThemeEvent() + { + var theme = new Theme(name: "my theme"); + await ArrangeDb.Themes.AddAsync(theme); + await ArrangeDb.SaveChangesAsync(); + + var handler = new CreateThemeEventCommand.Handler(ActDb, Mapper); + var command = new CreateThemeEventCommand + { + Name = "Test Theme", + GoldMultiplier = 1.5f, + ExpMultiplier = 2.0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + ActiveUntilUtc = DateTimeOffset.UtcNow.AddDays(7), + ThemeId = theme.Id, + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data!.Name, Is.EqualTo(command.Name)); + Assert.That(result.Data.GoldMultiplier, Is.EqualTo(command.GoldMultiplier)); + Assert.That(result.Data.ExpMultiplier, Is.EqualTo(command.ExpMultiplier)); + Assert.That(result.Data.ActiveFromUtc, Is.EqualTo(command.ActiveFromUtc)); + Assert.That(result.Data.ActiveUntilUtc, Is.EqualTo(command.ActiveUntilUtc)); + Assert.That(result.Data.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(command.RequiredEquipmentSlotsMatchingTheme)); + Assert.That(result.Data.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(command.MinumumRequiredEquipmentSlotsMatchingTheme)); + Assert.That(result.Data.EventTheme.Id, Is.EqualTo(command.ThemeId)); + + } + + [Test] + public async Task ShouldCreateThemeEventWithDefaultMultipliers() + { + var theme = new Theme(name: "my theme"); + await ArrangeDb.Themes.AddAsync(theme); + await ArrangeDb.SaveChangesAsync(); + + var handler = new CreateThemeEventCommand.Handler(ActDb, Mapper); + var command = new CreateThemeEventCommand + { + Name = "Default Theme", + ActiveFromUtc = DateTimeOffset.UtcNow, + ThemeId = theme.Id, + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data!.GoldMultiplier, Is.EqualTo(1.0f)); + Assert.That(result.Data.ExpMultiplier, Is.EqualTo(1.0f)); + Assert.That(result.Data.ActiveUntilUtc, Is.Null); + } + + [Test] + public async Task ShouldCreateThemeEventWithoutActiveUntil() + { + var theme = new Theme(name: "my theme"); + await ArrangeDb.Themes.AddAsync(theme); + await ArrangeDb.SaveChangesAsync(); + + var handler = new CreateThemeEventCommand.Handler(ActDb, Mapper); + var now = DateTimeOffset.UtcNow; + var command = new CreateThemeEventCommand + { + Name = "Indefinite Theme", + GoldMultiplier = 2.0f, + ExpMultiplier = 2.5f, + ActiveFromUtc = now, + ActiveUntilUtc = null, + ThemeId = theme.Id, + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data!.ActiveUntilUtc, Is.Null); + } + + [Test] + public async Task ShouldReturnErrorWhenThemeWasNotFound() + { + var handler = new CreateThemeEventCommand.Handler(ActDb, Mapper); + var now = DateTimeOffset.UtcNow; + var command = new CreateThemeEventCommand + { + Name = "Indefinite Theme", + GoldMultiplier = 2.0f, + ExpMultiplier = 2.5f, + ActiveFromUtc = now, + ActiveUntilUtc = null, + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Null); + Assert.That(result.Errors, Is.Not.Null); + + var error = result.Errors!.Single(); + Assert.That(error.Code.ToString(), Is.EqualTo("ThemeNotFound")); + } + + [Test] + public void ShouldFailValidationWhenNameIsEmpty() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = string.Empty, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors, Has.Count.GreaterThan(0)); + Assert.That(result.Errors[0].PropertyName, Is.EqualTo("Name")); + } + + [Test] + public void ShouldFailValidationWhenNameExceeds100Characters() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = new string('a', 101), + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "Name"), Is.True); + } + + [Test] + public void ShouldPassValidationWhenNameIs100Characters() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = new string('a', 100), + GoldMultiplier = 1.0f, + ExpMultiplier = 1.0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.True); + } + + [Test] + public void ShouldFailValidationWhenGoldMultiplierIsZero() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = 0f, + ExpMultiplier = 1.0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "GoldMultiplier"), Is.True); + } + + [Test] + public void ShouldFailValidationWhenGoldMultiplierIsNegative() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = -1.5f, + ExpMultiplier = 1.0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "GoldMultiplier"), Is.True); + } + + [Test] + public void ShouldFailValidationWhenExpMultiplierIsZero() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = 1.0f, + ExpMultiplier = 0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "ExpMultiplier"), Is.True); + } + + [Test] + public void ShouldFailValidationWhenExpMultiplierIsNegative() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = 1.0f, + ExpMultiplier = -2.0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "ExpMultiplier"), Is.True); + } + + [Test] + public void ShouldPassValidationWhenMessageIs1000Characters() + { + var validator = new CreateThemeEventCommand.Validator(); + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = 1.0f, + ExpMultiplier = 1.0f, + ActiveFromUtc = DateTimeOffset.UtcNow, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.True); + } + + [Test] + public void ShouldFailValidationWhenActiveUntilUtcIsBeforeActiveFromUtc() + { + var validator = new CreateThemeEventCommand.Validator(); + var now = DateTimeOffset.UtcNow; + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = 1.0f, + ExpMultiplier = 1.0f, + ActiveFromUtc = now, + ActiveUntilUtc = now.AddDays(-1), + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "ActiveUntilUtc"), Is.True); + } + + [Test] + public void ShouldPassValidationWhenActiveUntilUtcEqualsActiveFromUtc() + { + var validator = new CreateThemeEventCommand.Validator(); + var now = DateTimeOffset.UtcNow; + var command = new CreateThemeEventCommand + { + Name = "Test", + GoldMultiplier = 1.0f, + ExpMultiplier = 1.0f, + ActiveFromUtc = now, + ActiveUntilUtc = now, + }; + + var result = validator.Validate(command); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Errors.Any(e => e.PropertyName == "ActiveUntilUtc"), Is.True); + } + + [Test] + public async Task ShouldReturnThemeEventWithId() + { + var theme = new Theme(name: "my theme"); + await ArrangeDb.Themes.AddAsync(theme); + await ArrangeDb.SaveChangesAsync(); + + var handler = new CreateThemeEventCommand.Handler(ActDb, Mapper); + var command = new CreateThemeEventCommand + { + Name = "Theme With ID", + ActiveFromUtc = DateTimeOffset.UtcNow, + ThemeId = theme.Id, + }; + + var result = await handler.Handle(command, CancellationToken.None); + + Assert.That(result.Data, Is.Not.Null); + Assert.That(result.Data!.Id, Is.GreaterThan(0)); + } +} From 43b31a1f5762a6b946f36723e364b3d56c776430 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 21:05:11 +0200 Subject: [PATCH 07/38] Adds request to get active theme events to the crpg server --- src/Module.Server/Api/HttpCrpgClient.cs | 6 +++++ src/Module.Server/Api/ICrpgClient.cs | 3 +++ src/Module.Server/Api/Models/Themes/Theme.cs | 8 +++++++ .../Api/Models/Themes/ThemeEquipmentSlot.cs | 17 ++++++++++++++ .../Api/Models/Themes/ThemeEvent.cs | 22 +++++++++++++++++++ src/Module.Server/Api/StubCrpgClient.cs | 6 +++++ 6 files changed, 62 insertions(+) create mode 100644 src/Module.Server/Api/Models/Themes/Theme.cs create mode 100644 src/Module.Server/Api/Models/Themes/ThemeEquipmentSlot.cs create mode 100644 src/Module.Server/Api/Models/Themes/ThemeEvent.cs diff --git a/src/Module.Server/Api/HttpCrpgClient.cs b/src/Module.Server/Api/HttpCrpgClient.cs index e33b4a43b..61dd4d63d 100644 --- a/src/Module.Server/Api/HttpCrpgClient.cs +++ b/src/Module.Server/Api/HttpCrpgClient.cs @@ -7,6 +7,7 @@ using Crpg.Module.Api.Models.Clans; using Crpg.Module.Api.Models.GameEvents; using Crpg.Module.Api.Models.Restrictions; +using Crpg.Module.Api.Models.Themes; using Crpg.Module.Api.Models.Users; using Crpg.Module.Common; using Crpg.Module.Helpers.Json; @@ -116,6 +117,11 @@ public Task CreateGameEventsAsync(CrpgGameEventsCreateRequest req, CancellationT return Post("games/game-events", req, cancellationToken); } + public Task>> GetActiveThemeEvents(CancellationToken cancellationToken = default) + { + return Get>("games/themes/events/active", null, cancellationToken); + } + public void Dispose() => _httpClient.Dispose(); private Task> Get(string requestUri, Dictionary? queryParameters, diff --git a/src/Module.Server/Api/ICrpgClient.cs b/src/Module.Server/Api/ICrpgClient.cs index 3231644e8..2c80369db 100644 --- a/src/Module.Server/Api/ICrpgClient.cs +++ b/src/Module.Server/Api/ICrpgClient.cs @@ -3,6 +3,7 @@ using Crpg.Module.Api.Models.Clans; using Crpg.Module.Api.Models.GameEvents; using Crpg.Module.Api.Models.Restrictions; +using Crpg.Module.Api.Models.Themes; using Crpg.Module.Api.Models.Users; namespace Crpg.Module.Api; @@ -26,4 +27,6 @@ Task> RestrictUserAsync(CrpgRestrictionRequest req, CancellationToken cancellationToken = default); Task CreateGameEventsAsync(CrpgGameEventsCreateRequest req, CancellationToken cancellationToken = default); + + Task>> GetActiveThemeEvents(CancellationToken cancellationToken = default); } diff --git a/src/Module.Server/Api/Models/Themes/Theme.cs b/src/Module.Server/Api/Models/Themes/Theme.cs new file mode 100644 index 000000000..3c99625f5 --- /dev/null +++ b/src/Module.Server/Api/Models/Themes/Theme.cs @@ -0,0 +1,8 @@ +namespace Crpg.Module.Api.Models.Themes; + +internal class Theme +{ + public int Id { get; set; } + + public string Name { get; set; } = default!; +} diff --git a/src/Module.Server/Api/Models/Themes/ThemeEquipmentSlot.cs b/src/Module.Server/Api/Models/Themes/ThemeEquipmentSlot.cs new file mode 100644 index 000000000..841b2e172 --- /dev/null +++ b/src/Module.Server/Api/Models/Themes/ThemeEquipmentSlot.cs @@ -0,0 +1,17 @@ +namespace Crpg.Module.Api.Models.Themes; + +public enum ThemeEquipmentSlot +{ + Head, + Shoulder, + Body, + Hand, + Leg, + MountHarness, + Mount, + Weapon0, + Weapon1, + Weapon2, + Weapon3, + WeaponExtra, +} diff --git a/src/Module.Server/Api/Models/Themes/ThemeEvent.cs b/src/Module.Server/Api/Models/Themes/ThemeEvent.cs new file mode 100644 index 000000000..08b41de8d --- /dev/null +++ b/src/Module.Server/Api/Models/Themes/ThemeEvent.cs @@ -0,0 +1,22 @@ +namespace Crpg.Module.Api.Models.Themes; + +internal class ThemeEvent +{ + public int Id { get; set; } + + public string Name { get; set; } = default!; + + public float GoldMultiplier { get; set; } = 1.0f; + + public float ExpMultiplier { get; set; } = 1.0f; + + public DateTimeOffset ActiveFromUtc { get; set; } + + public DateTimeOffset? ActiveUntilUtc { get; set; } + + public List RequiredEquipmentSlotsMatchingTheme { get; set; } = new(); + + public int MinumumRequiredEquipmentSlotsMatchingTheme { get; set; } + + public Theme EventTheme { get; set; } = default!; +} diff --git a/src/Module.Server/Api/StubCrpgClient.cs b/src/Module.Server/Api/StubCrpgClient.cs index ed3cac6a5..7a9b11a75 100644 --- a/src/Module.Server/Api/StubCrpgClient.cs +++ b/src/Module.Server/Api/StubCrpgClient.cs @@ -5,6 +5,7 @@ using Crpg.Module.Api.Models.GameEvents; using Crpg.Module.Api.Models.Items; using Crpg.Module.Api.Models.Restrictions; +using Crpg.Module.Api.Models.Themes; using Crpg.Module.Api.Models.Users; using Crpg.Module.Common; using TaleWorlds.Core; @@ -129,6 +130,11 @@ public Task> RestrictUserAsync(CrpgRestrictionReques public Task CreateGameEventsAsync(CrpgGameEventsCreateRequest req, CancellationToken cancellationToken = default) { return Task.CompletedTask; + } + + public Task>> GetActiveThemeEvents(CancellationToken cancellationToken = default) + { + return Task.FromResult(new CrpgResult> { Data = new List() }); } public void Dispose() From b5c00691df6f0aa7042ec6c7da58e4a559ce762f Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sat, 13 Jun 2026 21:43:32 +0200 Subject: [PATCH 08/38] Add themes to items --- src/Application/Items/Models/ItemCreation.cs | 2 ++ src/Application/System/Commands/SeedDataCommand.cs | 6 ++++++ src/Domain/Entities/Items/Item.cs | 3 +++ src/Persistence/Configurations/ItemConfiguration.cs | 1 + 4 files changed, 12 insertions(+) diff --git a/src/Application/Items/Models/ItemCreation.cs b/src/Application/Items/Models/ItemCreation.cs index 1714fdbd8..6228226d8 100644 --- a/src/Application/Items/Models/ItemCreation.cs +++ b/src/Application/Items/Models/ItemCreation.cs @@ -1,3 +1,4 @@ +using Crpg.Application.Themes.Models; using Crpg.Domain.Entities; using Crpg.Domain.Entities.Items; @@ -20,4 +21,5 @@ public record ItemCreation public ItemArmorComponentViewModel? Armor { get; init; } public ItemMountComponentViewModel? Mount { get; init; } public IList Weapons { get; init; } = Array.Empty(); + public IList Themes { get; init; } = Array.Empty(); } diff --git a/src/Application/System/Commands/SeedDataCommand.cs b/src/Application/System/Commands/SeedDataCommand.cs index eef5a774c..07b1d7177 100644 --- a/src/Application/System/Commands/SeedDataCommand.cs +++ b/src/Application/System/Commands/SeedDataCommand.cs @@ -20,6 +20,7 @@ using Crpg.Domain.Entities.Servers; using Crpg.Domain.Entities.Settlements; using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; using Crpg.Domain.Entities.Users; using Crpg.Sdk.Abstractions; using Microsoft.EntityFrameworkCore; @@ -2905,6 +2906,11 @@ private Item ItemCreationToItem(ItemCreation item) res.TertiaryWeapon = IteamWeaponComponentFromViewModel(item.Weapons[2]); } + if (item.Themes != null) + { + res.Themes = item.Themes.Select(i => new Theme(i.Name) { Id = i.Id }).ToList(); + } + return res; } diff --git a/src/Domain/Entities/Items/Item.cs b/src/Domain/Entities/Items/Item.cs index aaa6665d1..96fc5b78e 100644 --- a/src/Domain/Entities/Items/Item.cs +++ b/src/Domain/Entities/Items/Item.cs @@ -1,4 +1,5 @@ using Crpg.Domain.Common; +using Crpg.Domain.Entities.Themes; namespace Crpg.Domain.Entities.Items; @@ -56,6 +57,8 @@ public class Item : AuditableEntity, ICloneable public List UserItems { get; set; } = new(); + public List Themes { get; set; } = new(); + public IEnumerable GetWeapons() { if (PrimaryWeapon != null) diff --git a/src/Persistence/Configurations/ItemConfiguration.cs b/src/Persistence/Configurations/ItemConfiguration.cs index ed74e58a9..87a91d50e 100644 --- a/src/Persistence/Configurations/ItemConfiguration.cs +++ b/src/Persistence/Configurations/ItemConfiguration.cs @@ -13,6 +13,7 @@ public void Configure(EntityTypeBuilder builder) builder.OwnsOne(i => i.PrimaryWeapon!, b => ConfigureItemWeaponComponent(b, "primary_")); builder.OwnsOne(i => i.SecondaryWeapon!, b => ConfigureItemWeaponComponent(b, "secondary_")); builder.OwnsOne(i => i.TertiaryWeapon!, b => ConfigureItemWeaponComponent(b, "tertiary_")); + builder.HasMany(i => i.Themes); } private static void ConfigureItemArmorComponent(OwnedNavigationBuilder builder) From d04f25e61a0eca6d19a99773d8616a1b0b0b12c1 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Sun, 14 Jun 2026 21:21:23 +0200 Subject: [PATCH 09/38] Adds eligible items to the theme event --- .../Themes/Models/ThemeEventItemViewModel.cs | 6 +++ .../Themes/Models/ThemeEventViewModel.cs | 10 ++++- .../Queries/GetActiveThemeEventsQuery.cs | 40 +++++++++++++++++-- .../Themes/Queries/GetThemeEventsQuery.cs | 39 ++++++++++++++++-- .../Themes/GetActiveThemeEventsQueryTest.cs | 10 +++-- .../Themes/GetThemeEventsQueryTest.cs | 10 +++-- 6 files changed, 99 insertions(+), 16 deletions(-) create mode 100644 src/Application/Themes/Models/ThemeEventItemViewModel.cs diff --git a/src/Application/Themes/Models/ThemeEventItemViewModel.cs b/src/Application/Themes/Models/ThemeEventItemViewModel.cs new file mode 100644 index 000000000..2efb95034 --- /dev/null +++ b/src/Application/Themes/Models/ThemeEventItemViewModel.cs @@ -0,0 +1,6 @@ +namespace Crpg.Application.Themes.Models; + +public class ThemeEventItemViewModel +{ + public string ItemId { get; init; } = default!; +} diff --git a/src/Application/Themes/Models/ThemeEventViewModel.cs b/src/Application/Themes/Models/ThemeEventViewModel.cs index 6959422c9..450260065 100644 --- a/src/Application/Themes/Models/ThemeEventViewModel.cs +++ b/src/Application/Themes/Models/ThemeEventViewModel.cs @@ -1,4 +1,5 @@ -using Crpg.Application.Common.Mappings; +using AutoMapper; +using Crpg.Application.Common.Mappings; using Crpg.Domain.Entities.Themes; namespace Crpg.Application.Themes.Models; @@ -45,5 +46,10 @@ public class ThemeEventViewModel : IMapFrom /// /// The theme of the event. /// - public Theme EventTheme { get; set; } = default!; + public ThemeViewModel EventTheme { get; set; } = default!; + + public List EligibleItemIds { get; set; } = new(); + + public void Mapping(Profile profile) => profile.CreateMap() + .ForMember(dest => dest.EligibleItemIds, opt => opt.Ignore()); } diff --git a/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs b/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs index 447d2dcf3..a9d13a6b9 100644 --- a/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs +++ b/src/Application/Themes/Queries/GetActiveThemeEventsQuery.cs @@ -3,24 +3,58 @@ using Crpg.Application.Common.Mediator; using Crpg.Application.Common.Results; using Crpg.Application.Themes.Models; +using Crpg.Domain.Entities.Themes; using Microsoft.EntityFrameworkCore; namespace Crpg.Application.Themes.Queries; public class GetActiveThemeEventsQuery : IMediatorRequest> { - internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler> + internal class Handler(ICrpgDbContext db) : IMediatorRequestHandler> { public async ValueTask>> Handle(GetActiveThemeEventsQuery req, CancellationToken cancellationToken) { var now = DateTime.UtcNow; - var activeThemes = await db.ThemeEvents.Include(x => x.EventTheme).Where(theme => now >= theme.ActiveFromUtc && (theme.ActiveUntilUtc == null || now <= theme.ActiveUntilUtc)) + var activeThemeEvents = await db.ThemeEvents + .Include(x => x.EventTheme) + .Where(te => te.ActiveFromUtc <= now && (te.ActiveUntilUtc == null || te.ActiveUntilUtc > now)) .AsNoTracking() .ToListAsync(cancellationToken); - var viewModels = mapper.Map>(activeThemes); + var themeIds = activeThemeEvents.Select(te => te.EventTheme.Id).Distinct().ToList(); + + var eligibleItemsByTheme = await db.Items + .Where(item => item.Enabled && item.Themes.Any(itemTheme => themeIds.Contains(itemTheme.Id))) + .Select(item => new { item.Id, ThemeIds = item.Themes.Select(t => t.Id) }) + .ToListAsync(cancellationToken); + + var itemIdsByTheme = eligibleItemsByTheme + .SelectMany(itemAndThemeIds => itemAndThemeIds.ThemeIds, (item, themeId) => new { item.Id, ThemeId = themeId }) + .GroupBy(x => x.ThemeId) + .ToDictionary(g => g.Key, g => g.Select(x => x.Id).ToList()); + + var viewModels = activeThemeEvents.Select(themeEvent => MapToViewModel(themeEvent, itemIdsByTheme)).ToList(); return new(viewModels); } } + + private static ThemeEventViewModel MapToViewModel(ThemeEvent themeEvent, Dictionary> itemIdsByTheme) + { + itemIdsByTheme.TryGetValue(themeEvent.EventTheme.Id, out List? itemIds); + + return new ThemeEventViewModel + { + Id = themeEvent.Id, + Name = themeEvent.Name, + GoldMultiplier = themeEvent.GoldMultiplier, + ExpMultiplier = themeEvent.ExpMultiplier, + ActiveFromUtc = themeEvent.ActiveFromUtc, + ActiveUntilUtc = themeEvent.ActiveUntilUtc, + RequiredEquipmentSlotsMatchingTheme = themeEvent.RequiredEquipmentSlotsMatchingTheme, + MinumumRequiredEquipmentSlotsMatchingTheme = themeEvent.MinumumRequiredEquipmentSlotsMatchingTheme, + EventTheme = new ThemeViewModel { Id = themeEvent.EventTheme.Id, Name = themeEvent.EventTheme.Name }, + EligibleItemIds = itemIds ?? new List(), + }; + } } diff --git a/src/Application/Themes/Queries/GetThemeEventsQuery.cs b/src/Application/Themes/Queries/GetThemeEventsQuery.cs index 9f0b6ae2f..0d5dbf5dc 100644 --- a/src/Application/Themes/Queries/GetThemeEventsQuery.cs +++ b/src/Application/Themes/Queries/GetThemeEventsQuery.cs @@ -3,20 +3,53 @@ using Crpg.Application.Common.Mediator; using Crpg.Application.Common.Results; using Crpg.Application.Themes.Models; +using Crpg.Domain.Entities.Themes; using Microsoft.EntityFrameworkCore; namespace Crpg.Application.Themes.Queries; public class GetThemeEventsQuery : IMediatorRequest> { - internal class Handler(ICrpgDbContext db, IMapper mapper) : IMediatorRequestHandler> + internal class Handler(ICrpgDbContext db) : IMediatorRequestHandler> { public async ValueTask>> Handle(GetThemeEventsQuery req, CancellationToken cancellationToken) { - var themes = await db.ThemeEvents.Include(x => x.EventTheme).AsNoTracking().ToListAsync(cancellationToken); - var viewModels = mapper.Map>(themes); + var themeEvents = await db.ThemeEvents.Include(x => x.EventTheme).AsNoTracking().ToListAsync(cancellationToken); + + var themeIds = themeEvents.Select(te => te.EventTheme.Id).Distinct().ToList(); + + var eligibleItemsByTheme = await db.Items + .Where(item => item.Enabled && item.Themes.Any(itemTheme => themeIds.Contains(itemTheme.Id))) + .Select(item => new { item.Id, ThemeIds = item.Themes.Select(t => t.Id) }) + .ToListAsync(cancellationToken); + + var itemIdsByTheme = eligibleItemsByTheme + .SelectMany(itemAndThemeIds => itemAndThemeIds.ThemeIds, (item, themeId) => new { item.Id, ThemeId = themeId }) + .GroupBy(x => x.ThemeId) + .ToDictionary(g => g.Key, g => g.Select(x => x.Id).ToList()); + + var viewModels = themeEvents.Select(themeEvent => MapToViewModel(themeEvent, itemIdsByTheme)).ToList(); return new(viewModels); } } + + private static ThemeEventViewModel MapToViewModel(ThemeEvent themeEvent, Dictionary> itemIdsByTheme) + { + itemIdsByTheme.TryGetValue(themeEvent.EventTheme.Id, out List? itemIds); + + return new ThemeEventViewModel + { + Id = themeEvent.Id, + Name = themeEvent.Name, + GoldMultiplier = themeEvent.GoldMultiplier, + ExpMultiplier = themeEvent.ExpMultiplier, + ActiveFromUtc = themeEvent.ActiveFromUtc, + ActiveUntilUtc = themeEvent.ActiveUntilUtc, + RequiredEquipmentSlotsMatchingTheme = themeEvent.RequiredEquipmentSlotsMatchingTheme, + MinumumRequiredEquipmentSlotsMatchingTheme = themeEvent.MinumumRequiredEquipmentSlotsMatchingTheme, + EventTheme = new ThemeViewModel { Id = themeEvent.EventTheme.Id, Name = themeEvent.EventTheme.Name }, + EligibleItemIds = itemIds ?? new List(), + }; + } } diff --git a/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs b/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs index fdb7039e6..ba3c7145a 100644 --- a/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs +++ b/test/Application.UTest/Themes/GetActiveThemeEventsQueryTest.cs @@ -9,7 +9,7 @@ public class GetActiveThemeEventsQueryTest : TestBase [Test] public async Task ShouldReturnEmptyWhenNoActiveThemeEvents() { - var handler = new GetActiveThemeEventsQuery.Handler(ActDb, Mapper); + var handler = new GetActiveThemeEventsQuery.Handler(ActDb); var result = await handler.Handle(new GetActiveThemeEventsQuery(), CancellationToken.None); Assert.That(result?.Data, Is.Empty); @@ -27,7 +27,7 @@ public async Task ShouldReturnActiveThemeEvents() ArrangeDb.ThemeEvents.AddRange(eventActiveForALimitedTime, eventActiveIndefinitely, eventThatHasntStartedYet, eventThatHasAlreadyEnded); await ArrangeDb.SaveChangesAsync(CancellationToken.None); - var handler = new GetActiveThemeEventsQuery.Handler(ActDb, Mapper); + var handler = new GetActiveThemeEventsQuery.Handler(ActDb); var result = await handler.Handle(new GetActiveThemeEventsQuery(), CancellationToken.None); @@ -45,7 +45,8 @@ public async Task ShouldReturnActiveThemeEvents() Assert.That(resultOne.ActiveUntilUtc, Is.EqualTo(eventActiveForALimitedTime.ActiveUntilUtc)); Assert.That(resultOne.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(eventActiveForALimitedTime.RequiredEquipmentSlotsMatchingTheme)); Assert.That(resultOne.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(eventActiveForALimitedTime.MinumumRequiredEquipmentSlotsMatchingTheme)); - Assert.That(resultOne.EventTheme, Is.EqualTo(eventActiveForALimitedTime.EventTheme).UsingPropertiesComparer()); + Assert.That(resultOne.EventTheme.Id, Is.EqualTo(eventActiveForALimitedTime.EventTheme.Id)); + Assert.That(resultOne.EventTheme.Name, Is.EqualTo(eventActiveForALimitedTime.EventTheme.Name)); var resultTwo = result.Data!.Single(x => x.Name == eventActiveIndefinitely.Name); Assert.That(resultTwo.Id, Is.GreaterThan(0)); @@ -56,7 +57,8 @@ public async Task ShouldReturnActiveThemeEvents() Assert.That(resultTwo.ActiveUntilUtc, Is.EqualTo(eventActiveIndefinitely.ActiveUntilUtc)); Assert.That(resultTwo.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(eventActiveIndefinitely.RequiredEquipmentSlotsMatchingTheme)); Assert.That(resultTwo.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(eventActiveIndefinitely.MinumumRequiredEquipmentSlotsMatchingTheme)); - Assert.That(resultTwo.EventTheme, Is.EqualTo(eventActiveIndefinitely.EventTheme).UsingPropertiesComparer()); + Assert.That(resultTwo.EventTheme.Id, Is.EqualTo(eventActiveIndefinitely.EventTheme.Id)); + Assert.That(resultTwo.EventTheme.Name, Is.EqualTo(eventActiveIndefinitely.EventTheme.Name)); } private static ThemeEvent CreateDefaultTheme( diff --git a/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs b/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs index 60e28818e..38b9e3d78 100644 --- a/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs +++ b/test/Application.UTest/Themes/GetThemeEventsQueryTest.cs @@ -9,7 +9,7 @@ public class GetThemeEventsQueryTest : TestBase [Test] public async Task ShouldReturnEmptyWhenNoThemeEvents() { - var handler = new GetThemeEventsQuery.Handler(ActDb, Mapper); + var handler = new GetThemeEventsQuery.Handler(ActDb); var result = await handler.Handle(new GetThemeEventsQuery(), CancellationToken.None); Assert.That(result?.Data, Is.Empty); @@ -23,7 +23,7 @@ public async Task ShouldReturnThemeEvents() ArrangeDb.ThemeEvents.AddRange(themeEventOne, themeEventTwo); await ArrangeDb.SaveChangesAsync(CancellationToken.None); - var handler = new GetThemeEventsQuery.Handler(ActDb, Mapper); + var handler = new GetThemeEventsQuery.Handler(ActDb); var result = await handler.Handle(new GetThemeEventsQuery(), CancellationToken.None); @@ -41,7 +41,8 @@ public async Task ShouldReturnThemeEvents() Assert.That(resultOne.ActiveUntilUtc, Is.EqualTo(themeEventOne.ActiveUntilUtc)); Assert.That(resultOne.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(themeEventOne.RequiredEquipmentSlotsMatchingTheme)); Assert.That(resultOne.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(themeEventOne.MinumumRequiredEquipmentSlotsMatchingTheme)); - Assert.That(resultOne.EventTheme, Is.EqualTo(themeEventOne.EventTheme).UsingPropertiesComparer()); + Assert.That(resultOne.EventTheme.Id, Is.EqualTo(themeEventOne.EventTheme.Id)); + Assert.That(resultOne.EventTheme.Name, Is.EqualTo(themeEventOne.EventTheme.Name)); var resultTwo = result.Data!.Single(x => x.Name == themeEventTwo.Name); Assert.That(resultTwo.Id, Is.GreaterThan(0)); @@ -52,7 +53,8 @@ public async Task ShouldReturnThemeEvents() Assert.That(resultTwo.ActiveUntilUtc, Is.EqualTo(themeEventTwo.ActiveUntilUtc)); Assert.That(resultTwo.RequiredEquipmentSlotsMatchingTheme, Is.EquivalentTo(themeEventTwo.RequiredEquipmentSlotsMatchingTheme)); Assert.That(resultTwo.MinumumRequiredEquipmentSlotsMatchingTheme, Is.EqualTo(themeEventTwo.MinumumRequiredEquipmentSlotsMatchingTheme)); - Assert.That(resultTwo.EventTheme, Is.EqualTo(themeEventTwo.EventTheme).UsingPropertiesComparer()); + Assert.That(resultTwo.EventTheme.Id, Is.EqualTo(themeEventTwo.EventTheme.Id)); + Assert.That(resultTwo.EventTheme.Name, Is.EqualTo(themeEventTwo.EventTheme.Name)); } private static ThemeEvent CreateDefaultTheme( From 463c5ce7e445476463c9d03ba61ae3ef48b71836 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Mon, 15 Jun 2026 13:46:14 +0200 Subject: [PATCH 10/38] Fixes item theme db relation --- .../System/Commands/SeedDataCommand.cs | 5 +- .../Configurations/ItemConfiguration.cs | 2 +- ...113350_FixItemAndThemeRelation.Designer.cs | 3353 +++++++++++++++++ .../20260615113350_FixItemAndThemeRelation.cs | 50 + .../Migrations/CrpgDbContextModelSnapshot.cs | 36 + 5 files changed, 3444 insertions(+), 2 deletions(-) create mode 100644 src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.Designer.cs create mode 100644 src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.cs diff --git a/src/Application/System/Commands/SeedDataCommand.cs b/src/Application/System/Commands/SeedDataCommand.cs index 07b1d7177..ddee08a06 100644 --- a/src/Application/System/Commands/SeedDataCommand.cs +++ b/src/Application/System/Commands/SeedDataCommand.cs @@ -2784,7 +2784,10 @@ Task GetSettlementByName(string name) => private async Task CreateOrUpdateItems(CancellationToken cancellationToken) { var itemsById = (await _itemsSource.LoadItems()).ToDictionary(i => i.Id); - var dbItemsById = await _db.Items.ToDictionaryAsync(i => i.Id, cancellationToken); + var dbItemsById = await _db.Items + .Include(i => i.Themes) + .AsSplitQuery() + .ToDictionaryAsync(i => i.Id, cancellationToken); foreach (ItemCreation item in itemsById.Values) { diff --git a/src/Persistence/Configurations/ItemConfiguration.cs b/src/Persistence/Configurations/ItemConfiguration.cs index 87a91d50e..a82aeab21 100644 --- a/src/Persistence/Configurations/ItemConfiguration.cs +++ b/src/Persistence/Configurations/ItemConfiguration.cs @@ -13,7 +13,7 @@ public void Configure(EntityTypeBuilder builder) builder.OwnsOne(i => i.PrimaryWeapon!, b => ConfigureItemWeaponComponent(b, "primary_")); builder.OwnsOne(i => i.SecondaryWeapon!, b => ConfigureItemWeaponComponent(b, "secondary_")); builder.OwnsOne(i => i.TertiaryWeapon!, b => ConfigureItemWeaponComponent(b, "tertiary_")); - builder.HasMany(i => i.Themes); + builder.HasMany(i => i.Themes).WithMany(); } private static void ConfigureItemArmorComponent(OwnedNavigationBuilder builder) diff --git a/src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.Designer.cs b/src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.Designer.cs new file mode 100644 index 000000000..03728c666 --- /dev/null +++ b/src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.Designer.cs @@ -0,0 +1,3353 @@ +// +using System; +using System.Collections.Generic; +using Crpg.Domain.Entities; +using Crpg.Domain.Entities.ActivityLogs; +using Crpg.Domain.Entities.Battles; +using Crpg.Domain.Entities.Characters; +using Crpg.Domain.Entities.Clans; +using Crpg.Domain.Entities.Items; +using Crpg.Domain.Entities.Marketplace; +using Crpg.Domain.Entities.Notifications; +using Crpg.Domain.Entities.Parties; +using Crpg.Domain.Entities.Quests; +using Crpg.Domain.Entities.Restrictions; +using Crpg.Domain.Entities.Servers; +using Crpg.Domain.Entities.Settlements; +using Crpg.Domain.Entities.Terrains; +using Crpg.Domain.Entities.Themes; +using Crpg.Domain.Entities.Users; +using Crpg.Persistence; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using NetTopologySuite.Geometries; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Crpg.Persistence.Migrations +{ + [DbContext(typeof(CrpgDbContext))] + [Migration("20260615113350_FixItemAndThemeRelation")] + partial class FixItemAndThemeRelation + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.7") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "activity_log_type", new[] { "battle_apply_as_mercenary", "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked", "battle_participant_leaved", "character_created", "character_deleted", "character_earned", "character_rating_reset", "character_respecialized", "character_retired", "character_rewarded", "chat_message_sent", "clan_application_accepted", "clan_application_created", "clan_application_declined", "clan_armory_add_item", "clan_armory_borrow_item", "clan_armory_remove_item", "clan_armory_return_item", "clan_created", "clan_deleted", "clan_member_kicked", "clan_member_leaved", "clan_member_role_edited", "item_bought", "item_broke", "item_reforged", "item_repaired", "item_returned", "item_sold", "item_upgraded", "marketplace_listing_accepted", "marketplace_listing_cancelled", "marketplace_listing_created", "marketplace_listing_expired", "marketplace_listing_invalidated", "quest_rerolled", "quest_reward_claimed", "server_joined", "team_hit", "team_hit_reported", "team_hit_reported_user_kicked", "user_created", "user_deleted", "user_renamed", "user_rewarded" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_fighter_application_status", new[] { "accepted", "declined", "intent", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_mercenary_application_status", new[] { "accepted", "declined", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_participant_type", new[] { "clan_member", "mercenary", "party" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_phase", new[] { "end", "hiring", "live", "preparation", "scheduled" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "battle_side", new[] { "attacker", "defender" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "character_class", new[] { "archer", "cavalry", "crossbowman", "infantry", "mounted_archer", "peasant", "shock_infantry", "skirmisher" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_status", new[] { "accepted", "declined", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_invitation_type", new[] { "offer", "request" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "clan_member_role", new[] { "leader", "member", "officer" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "culture", new[] { "aserai", "battania", "empire", "khuzait", "looters", "neutral", "sturgia", "vlandia" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "damage_type", new[] { "blunt", "cut", "pierce", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "game_mode", new[] { "crpg_battle", "crpg_captain", "crpg_conquest", "crpg_duel", "crpg_siege", "crpg_skirmish", "crpg_team_deathmatch", "crpg_unknown_game_mode", "crpgdtv" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "item_type", new[] { "arrows", "banner", "body_armor", "bolts", "bow", "bullets", "crossbow", "hand_armor", "head_armor", "leg_armor", "mount", "mount_harness", "musket", "one_handed_weapon", "pistol", "polearm", "shield", "shoulder_armor", "thrown", "two_handed_weapon", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "languages", new[] { "be", "bg", "cs", "da", "de", "el", "en", "es", "fi", "fr", "hr", "hu", "it", "lv", "nl", "no", "pl", "pt", "ro", "ru", "sr", "sv", "tr", "uk", "zh" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "marketplace_listing_asset_side", new[] { "offered", "requested" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_state", new[] { "read", "unread" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "notification_type", new[] { "battle_mercenary_application_accepted", "battle_mercenary_application_declined", "battle_participant_kicked_to_ex_participant", "character_rewarded_to_user", "clan_application_accepted_to_user", "clan_application_created_to_officers", "clan_application_created_to_user", "clan_application_declined_to_user", "clan_armory_borrow_item_to_lender", "clan_armory_remove_item_to_borrower", "clan_member_kicked_to_ex_member", "clan_member_leaved_to_leader", "clan_member_role_changed_to_user", "item_returned", "marketplace_listing_accepted_to_buyer", "marketplace_listing_accepted_to_seller", "marketplace_listing_expired", "marketplace_listing_invalidated", "user_rewarded_to_user" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_order_type", new[] { "attack_party", "attack_settlement", "follow_party", "join_battle", "move_to_point", "move_to_settlement", "transfer_offer_party" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_status", new[] { "awaiting_battle_join_decision", "awaiting_party_offer_decision", "idle", "idle_in_settlement", "in_battle", "recruiting_in_settlement" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "party_transfer_offer_status", new[] { "intent", "pending" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "platform", new[] { "epic_games", "microsoft", "steam" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_aggregation_type", new[] { "count", "sum" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "quest_type", new[] { "daily", "weekly" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "region", new[] { "as", "eu", "na", "oc" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "restriction_type", new[] { "all", "chat", "join" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "role", new[] { "admin", "game_admin", "moderator", "user" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "settlement_type", new[] { "castle", "town", "village" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "terrain_type", new[] { "barrier", "deep_water", "plain", "shallow_water", "sparse_forest", "thick_forest" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "theme_equipment_slot", new[] { "body", "hand", "head", "leg", "mount", "mount_harness", "shoulder", "weapon0", "weapon1", "weapon2", "weapon3", "weapon_extra" }); + NpgsqlModelBuilderExtensions.HasPostgresEnum(modelBuilder, "weapon_class", new[] { "arrow", "banner", "bolt", "boulder", "bow", "cartridge", "crossbow", "dagger", "javelin", "large_shield", "low_grip_polearm", "mace", "musket", "one_handed_axe", "one_handed_polearm", "one_handed_sword", "pick", "pistol", "small_shield", "stone", "throwing_axe", "throwing_knife", "two_handed_axe", "two_handed_mace", "two_handed_polearm", "two_handed_sword", "undefined" }); + NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis"); + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("BattleParticipantStatistic", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Assists") + .HasColumnType("integer") + .HasColumnName("assists"); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("Deaths") + .HasColumnType("integer") + .HasColumnName("deaths"); + + b.Property("Kills") + .HasColumnType("integer") + .HasColumnName("kills"); + + b.Property("ParticipantId") + .HasColumnType("integer") + .HasColumnName("participant_id"); + + b.Property("Participated") + .HasColumnType("boolean") + .HasColumnName("participated"); + + b.HasKey("Id") + .HasName("pk_battle_participant_statistic"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_participant_statistic_battle_id"); + + b.HasIndex("ParticipantId") + .IsUnique() + .HasDatabaseName("ix_battle_participant_statistic_participant_id"); + + b.ToTable("battle_participant_statistic", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Type") + .HasColumnType("activity_log_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_activity_logs"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_activity_logs_user_id"); + + b.HasIndex("CreatedAt", "UserId") + .HasDatabaseName("ix_activity_logs_created_at_user_id"); + + b.ToTable("activity_logs", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => + { + b.Property("ActivityLogId") + .HasColumnType("integer") + .HasColumnName("activity_log_id"); + + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("ActivityLogId", "Key") + .HasName("pk_activity_log_metadata"); + + b.ToTable("activity_log_metadata", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Phase") + .HasColumnType("battle_phase") + .HasColumnName("phase"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("ScheduledFor") + .HasColumnType("timestamp with time zone") + .HasColumnName("scheduled_for"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battles"); + + b.ToTable("battles", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("Commander") + .HasColumnType("boolean") + .HasColumnName("commander"); + + b.Property("ParticipantSlots") + .HasColumnType("integer") + .HasColumnName("participant_slots"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("SettlementId") + .HasColumnType("integer") + .HasColumnName("settlement_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.HasKey("Id") + .HasName("pk_battle_fighters"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_fighters_battle_id"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_battle_fighters_party_id"); + + b.HasIndex("SettlementId") + .HasDatabaseName("ix_battle_fighters_settlement_id"); + + b.ToTable("battle_fighters", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Status") + .HasColumnType("battle_fighter_application_status") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battle_fighter_applications"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_fighter_applications_battle_id"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_battle_fighter_applications_party_id"); + + b.ToTable("battle_fighter_applications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Status") + .HasColumnType("battle_mercenary_application_status") + .HasColumnName("status"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Wage") + .HasColumnType("integer") + .HasColumnName("wage"); + + b.HasKey("Id") + .HasName("pk_battle_mercenary_applications"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_mercenary_applications_battle_id"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_battle_mercenary_applications_character_id"); + + b.ToTable("battle_mercenary_applications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CaptainFighterId") + .HasColumnType("integer") + .HasColumnName("captain_fighter_id"); + + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("MercenaryApplicationId") + .HasColumnType("integer") + .HasColumnName("mercenary_application_id"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("Type") + .HasColumnType("battle_participant_type") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_battle_participants"); + + b.HasIndex("BattleId") + .HasDatabaseName("ix_battle_participants_battle_id"); + + b.HasIndex("CaptainFighterId") + .HasDatabaseName("ix_battle_participants_captain_fighter_id"); + + b.HasIndex("CharacterId") + .HasDatabaseName("ix_battle_participants_character_id"); + + b.HasIndex("MercenaryApplicationId") + .HasDatabaseName("ix_battle_participants_mercenary_application_id"); + + b.ToTable("battle_participants", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BattleId") + .HasColumnType("integer") + .HasColumnName("battle_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Side") + .HasColumnType("battle_side") + .HasColumnName("side"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_battle_side_briefings"); + + b.HasIndex("BattleId", "Side") + .IsUnique() + .HasDatabaseName("ix_battle_side_briefings_battle_id_side"); + + b.ToTable("battle_side_briefings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Class") + .HasColumnType("character_class") + .HasColumnName("class"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("Experience") + .HasColumnType("integer") + .HasColumnName("experience"); + + b.Property("ForTournament") + .HasColumnType("boolean") + .HasColumnName("for_tournament"); + + b.Property("Generation") + .HasColumnType("integer") + .HasColumnName("generation"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_characters"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_characters_user_id"); + + b.ToTable("characters", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArmoryTimeout") + .HasColumnType("interval") + .HasColumnName("armory_timeout"); + + b.Property("BannerKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("banner_key"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Description") + .IsRequired() + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("Discord") + .HasColumnType("text") + .HasColumnName("discord"); + + b.PrimitiveCollection("Languages") + .IsRequired() + .HasColumnType("languages[]") + .HasColumnName("languages"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("PrimaryColor") + .HasColumnType("bigint") + .HasColumnName("primary_color"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("SecondaryColor") + .HasColumnType("bigint") + .HasColumnName("secondary_color"); + + b.Property("Tag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tag"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_clans"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_clans_name"); + + b.HasIndex("Tag") + .IsUnique() + .HasDatabaseName("ix_clans_tag"); + + b.ToTable("clans", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("BorrowerClanId") + .HasColumnType("integer") + .HasColumnName("borrower_clan_id"); + + b.Property("BorrowerUserId") + .HasColumnType("integer") + .HasColumnName("borrower_user_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_clan_armory_borrowed_items"); + + b.HasIndex("BorrowerClanId") + .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_clan_id"); + + b.HasIndex("BorrowerUserId") + .HasDatabaseName("ix_clan_armory_borrowed_items_borrower_user_id"); + + b.ToTable("clan_armory_borrowed_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClanId") + .HasColumnType("integer") + .HasColumnName("clan_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("InviteeId") + .HasColumnType("integer") + .HasColumnName("invitee_id"); + + b.Property("InviterId") + .HasColumnType("integer") + .HasColumnName("inviter_id"); + + b.Property("Status") + .HasColumnType("clan_invitation_status") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("clan_invitation_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_clan_invitations"); + + b.HasIndex("ClanId") + .HasDatabaseName("ix_clan_invitations_clan_id"); + + b.HasIndex("InviteeId") + .HasDatabaseName("ix_clan_invitations_invitee_id"); + + b.HasIndex("InviterId") + .HasDatabaseName("ix_clan_invitations_inviter_id"); + + b.ToTable("clan_invitations", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("ClanId") + .HasColumnType("integer") + .HasColumnName("clan_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Role") + .HasColumnType("clan_member_role") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserId") + .HasName("pk_clan_members"); + + b.HasIndex("ClanId") + .HasDatabaseName("ix_clan_members_clan_id"); + + b.ToTable("clan_members", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventData") + .HasColumnType("jsonb") + .HasColumnName("event_data"); + + b.Property("GameMode") + .HasColumnType("game_mode") + .HasColumnName("game_mode"); + + b.Property("Instance") + .IsRequired() + .HasColumnType("text") + .HasColumnName("instance"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_game_events"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("ix_game_events_created_at"); + + b.HasIndex("UserId", "Type", "CreatedAt") + .HasDatabaseName("ix_game_events_user_id_type_created_at"); + + b.ToTable("game_events", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("LenderClanId") + .HasColumnType("integer") + .HasColumnName("lender_clan_id"); + + b.Property("LenderUserId") + .HasColumnType("integer") + .HasColumnName("lender_user_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_clan_armory_items"); + + b.HasIndex("LenderClanId") + .HasDatabaseName("ix_clan_armory_items_lender_clan_id"); + + b.HasIndex("LenderUserId") + .HasDatabaseName("ix_clan_armory_items_lender_user_id"); + + b.ToTable("clan_armory_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("Slot") + .HasColumnType("item_slot") + .HasColumnName("slot"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.HasKey("CharacterId", "Slot") + .HasName("pk_equipped_items"); + + b.HasIndex("UserItemId") + .HasDatabaseName("ix_equipped_items_user_item_id"); + + b.ToTable("equipped_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.Property("Id") + .HasColumnType("text") + .HasColumnName("id"); + + b.Property("BaseId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("base_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Culture") + .HasColumnType("culture") + .HasColumnName("culture"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("Rank") + .HasColumnType("integer") + .HasColumnName("rank"); + + b.Property("Requirement") + .HasColumnType("integer") + .HasColumnName("requirement"); + + b.Property("Tier") + .HasColumnType("real") + .HasColumnName("tier"); + + b.Property("Type") + .HasColumnType("item_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Weight") + .HasColumnType("real") + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_items"); + + b.ToTable("items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ItemId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("PartyTransferOfferId") + .HasColumnType("integer") + .HasColumnName("party_transfer_offer_id"); + + b.Property("SettlementId") + .HasColumnType("integer") + .HasColumnName("settlement_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_item_stacks"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_item_stacks_item_id"); + + b.HasIndex("PartyId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_party_id_item_id") + .HasFilter("party_id IS NOT NULL"); + + b.HasIndex("PartyTransferOfferId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_party_transfer_offer_id_item_id") + .HasFilter("party_transfer_offer_id IS NOT NULL"); + + b.HasIndex("SettlementId", "ItemId") + .IsUnique() + .HasDatabaseName("ix_item_stacks_settlement_id_item_id") + .HasFilter("settlement_id IS NOT NULL"); + + b.ToTable("item_stacks", null, t => + { + t.HasCheckConstraint("CK_item_stacks_single_owner", "(party_id IS NOT NULL)::int + (settlement_id IS NOT NULL)::int + (party_transfer_offer_id IS NOT NULL)::int = 1"); + }); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => + { + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("UserItemId") + .HasName("pk_personal_items"); + + b.ToTable("personal_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("IsBroken") + .HasColumnType("boolean") + .HasColumnName("is_broken"); + + b.Property("ItemId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_items"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_user_items_item_id"); + + b.HasIndex("UserId", "ItemId") + .HasDatabaseName("ix_user_items_user_id_item_id"); + + b.ToTable("user_items", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("character varying(300)") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_item_presets"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_item_presets_user_id"); + + b.ToTable("user_item_presets", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => + { + b.Property("UserItemPresetId") + .HasColumnType("integer") + .HasColumnName("user_item_preset_id"); + + b.Property("Slot") + .HasColumnType("item_slot") + .HasColumnName("slot"); + + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.HasKey("UserItemPresetId", "Slot") + .HasName("pk_user_item_preset_slots"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_user_item_preset_slots_item_id"); + + b.ToTable("user_item_preset_slots", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => + { + b.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b.Property("LastRespecializeAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_respecialize_at"); + + b.HasKey("CharacterId") + .HasName("pk_character_limitations"); + + b.ToTable("character_limitations", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("GoldFee") + .HasColumnType("integer") + .HasColumnName("gold_fee"); + + b.Property("SellerId") + .HasColumnType("integer") + .HasColumnName("seller_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_marketplace_listings"); + + b.HasIndex("CreatedAt") + .HasDatabaseName("ix_marketplace_listings_created_at"); + + b.HasIndex("ExpiresAt") + .HasDatabaseName("ix_marketplace_listings_expires_at"); + + b.HasIndex("SellerId", "CreatedAt") + .HasDatabaseName("ix_marketplace_listings_seller_id_created_at"); + + b.ToTable("marketplace_listings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("HeirloomPoints") + .HasColumnType("integer") + .HasColumnName("heirloom_points"); + + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("MarketplaceListingId") + .HasColumnType("integer") + .HasColumnName("marketplace_listing_id"); + + b.Property("Side") + .HasColumnType("marketplace_listing_asset_side") + .HasColumnName("side"); + + b.Property("UserItemId") + .HasColumnType("integer") + .HasColumnName("user_item_id"); + + b.HasKey("Id") + .HasName("pk_marketplace_listing_assets"); + + b.HasIndex("ItemId") + .HasDatabaseName("ix_marketplace_listing_assets_item_id"); + + b.HasIndex("UserItemId") + .HasDatabaseName("ix_marketplace_listing_assets_user_item_id"); + + b.HasIndex("MarketplaceListingId", "Side") + .HasDatabaseName("ix_marketplace_listing_assets_marketplace_listing_id_side"); + + b.ToTable("marketplace_listing_assets", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("State") + .HasColumnType("notification_state") + .HasColumnName("state"); + + b.Property("Type") + .HasColumnType("notification_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("pk_user_notifications"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_notifications_user_id"); + + b.ToTable("user_notifications", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => + { + b.Property("UserNotificationId") + .HasColumnType("integer") + .HasColumnName("user_notification_id"); + + b.Property("Key") + .HasColumnType("text") + .HasColumnName("key"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text") + .HasColumnName("value"); + + b.HasKey("UserNotificationId", "Key") + .HasName("pk_user_notification_metadata"); + + b.ToTable("user_notification_metadata", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("id"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CurrentBattleId") + .HasColumnType("integer") + .HasColumnName("current_battle_id"); + + b.Property("CurrentPartyId") + .HasColumnType("integer") + .HasColumnName("current_party_id"); + + b.Property("CurrentSettlementId") + .HasColumnType("integer") + .HasColumnName("current_settlement_id"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Status") + .HasColumnType("party_status") + .HasColumnName("status"); + + b.Property("Troops") + .HasColumnType("real") + .HasColumnName("troops"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_parties"); + + b.HasIndex("CurrentBattleId") + .HasDatabaseName("ix_parties_current_battle_id"); + + b.HasIndex("CurrentPartyId") + .HasDatabaseName("ix_parties_current_party_id"); + + b.HasIndex("CurrentSettlementId") + .HasDatabaseName("ix_parties_current_settlement_id"); + + b.ToTable("parties", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderIndex") + .HasColumnType("integer") + .HasColumnName("order_index"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("TargetedBattleId") + .HasColumnType("integer") + .HasColumnName("targeted_battle_id"); + + b.Property("TargetedPartyId") + .HasColumnType("integer") + .HasColumnName("targeted_party_id"); + + b.Property("TargetedSettlementId") + .HasColumnType("integer") + .HasColumnName("targeted_settlement_id"); + + b.Property("Type") + .HasColumnType("party_order_type") + .HasColumnName("type"); + + b.Property("Waypoints") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("waypoints"); + + b.HasKey("Id") + .HasName("pk_party_orders"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_party_orders_party_id"); + + b.HasIndex("TargetedBattleId") + .HasDatabaseName("ix_party_orders_targeted_battle_id"); + + b.HasIndex("TargetedPartyId") + .HasDatabaseName("ix_party_orders_targeted_party_id"); + + b.HasIndex("TargetedSettlementId") + .HasDatabaseName("ix_party_orders_targeted_settlement_id"); + + b.ToTable("party_orders", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("PartyId") + .HasColumnType("integer") + .HasColumnName("party_id"); + + b.Property("Status") + .HasColumnType("party_transfer_offer_status") + .HasColumnName("status"); + + b.Property("TargetPartyId") + .HasColumnType("integer") + .HasColumnName("target_party_id"); + + b.Property("Troops") + .HasColumnType("real") + .HasColumnName("troops"); + + b.HasKey("Id") + .HasName("pk_party_transfer_offers"); + + b.HasIndex("PartyId") + .HasDatabaseName("ix_party_transfer_offers_party_id"); + + b.HasIndex("TargetPartyId") + .HasDatabaseName("ix_party_transfer_offers_target_party_id"); + + b.ToTable("party_transfer_offers", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.QuestDefinition", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AggregationField") + .HasColumnType("integer") + .HasColumnName("aggregation_field"); + + b.Property("AggregationType") + .HasColumnType("quest_aggregation_type") + .HasColumnName("aggregation_type"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventFiltersJson") + .HasColumnType("jsonb") + .HasColumnName("event_filters_json"); + + b.Property("EventType") + .HasColumnType("integer") + .HasColumnName("event_type"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("is_active"); + + b.Property("RequiredValue") + .HasColumnType("integer") + .HasColumnName("required_value"); + + b.Property("RewardExperience") + .HasColumnType("integer") + .HasColumnName("reward_experience"); + + b.Property("RewardGold") + .HasColumnType("integer") + .HasColumnName("reward_gold"); + + b.Property("Type") + .HasColumnType("quest_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_quest_definitions"); + + b.ToTable("quest_definitions", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("IsRewardClaimed") + .HasColumnType("boolean") + .HasColumnName("is_reward_claimed"); + + b.Property("QuestDefinitionId") + .HasColumnType("integer") + .HasColumnName("quest_definition_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("user_id"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_user_quests"); + + b.HasIndex("QuestDefinitionId") + .HasDatabaseName("ix_user_quests_quest_definition_id"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_user_quests_user_id"); + + b.ToTable("user_quests", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("expires_at"); + + b.Property("QuestDefinitionId") + .HasColumnType("integer") + .HasColumnName("quest_definition_id"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_weekly_quest_assignments"); + + b.HasIndex("ExpiresAt") + .HasDatabaseName("ix_weekly_quest_assignments_expires_at"); + + b.HasIndex("QuestDefinitionId") + .HasDatabaseName("ix_weekly_quest_assignments_quest_definition_id"); + + b.ToTable("weekly_quest_assignments", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Duration") + .HasColumnType("interval") + .HasColumnName("duration"); + + b.Property("PublicReason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("public_reason"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RestrictedByUserId") + .HasColumnType("integer") + .HasColumnName("restricted_by_user_id"); + + b.Property("RestrictedUserId") + .HasColumnType("integer") + .HasColumnName("restricted_user_id"); + + b.Property("Type") + .HasColumnType("restriction_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_restrictions"); + + b.HasIndex("RestrictedByUserId") + .HasDatabaseName("ix_restrictions_restricted_by_user_id"); + + b.HasIndex("RestrictedUserId") + .HasDatabaseName("ix_restrictions_restricted_user_id"); + + b.ToTable("restrictions", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settings.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Discord") + .IsRequired() + .HasColumnType("text") + .HasColumnName("discord"); + + b.Property("Github") + .IsRequired() + .HasColumnType("text") + .HasColumnName("github"); + + b.Property("HappyHours") + .IsRequired() + .HasColumnType("text") + .HasColumnName("happy_hours"); + + b.Property("ModDb") + .IsRequired() + .HasColumnType("text") + .HasColumnName("mod_db"); + + b.Property("Patreon") + .IsRequired() + .HasColumnType("text") + .HasColumnName("patreon"); + + b.Property("Reddit") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reddit"); + + b.Property("Steam") + .IsRequired() + .HasColumnType("text") + .HasColumnName("steam"); + + b.HasKey("Id") + .HasName("pk_settings"); + + b.ToTable("settings", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Culture") + .HasColumnType("culture") + .HasColumnName("culture"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("owner_id"); + + b.Property("Position") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("position"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("Scene") + .IsRequired() + .HasColumnType("text") + .HasColumnName("scene"); + + b.Property("Troops") + .HasColumnType("integer") + .HasColumnName("troops"); + + b.Property("Type") + .HasColumnType("settlement_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_settlements"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_settlements_owner_id"); + + b.HasIndex("Region", "Name") + .IsUnique() + .HasDatabaseName("ix_settlements_region_name"); + + b.ToTable("settlements", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Terrains.Terrain", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Boundary") + .IsRequired() + .HasColumnType("geometry") + .HasColumnName("boundary"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Type") + .HasColumnType("terrain_type") + .HasColumnName("type"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_terrains"); + + b.ToTable("terrains", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.Theme", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_themes"); + + b.HasIndex("Name") + .HasDatabaseName("ix_themes_name"); + + b.ToTable("themes", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.ThemeEvent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveFromUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("active_from_utc"); + + b.Property("ActiveUntilUtc") + .HasColumnType("timestamp with time zone") + .HasColumnName("active_until_utc"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("EventThemeId") + .HasColumnType("integer") + .HasColumnName("event_theme_id"); + + b.Property("ExpMultiplier") + .HasColumnType("real") + .HasColumnName("exp_multiplier"); + + b.Property("GoldMultiplier") + .HasColumnType("real") + .HasColumnName("gold_multiplier"); + + b.Property("MinumumRequiredEquipmentSlotsMatchingTheme") + .HasColumnType("integer") + .HasColumnName("minumum_required_equipment_slots_matching_theme"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.PrimitiveCollection>("RequiredEquipmentSlotsMatchingTheme") + .IsRequired() + .HasColumnType("theme_equipment_slot[]") + .HasColumnName("required_equipment_slots_matching_theme"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.HasKey("Id") + .HasName("pk_theme_events"); + + b.HasIndex("EventThemeId") + .HasDatabaseName("ix_theme_events_event_theme_id"); + + b.HasIndex("Name") + .HasDatabaseName("ix_theme_events_name"); + + b.ToTable("theme_events", (string)null); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ActiveCharacterId") + .HasColumnType("integer") + .HasColumnName("active_character_id"); + + b.Property("Avatar") + .HasColumnType("text") + .HasColumnName("avatar"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("ExperienceMultiplier") + .HasColumnType("real") + .HasColumnName("experience_multiplier"); + + b.Property("Gold") + .HasColumnType("integer") + .HasColumnName("gold"); + + b.Property("HeirloomPoints") + .HasColumnType("integer") + .HasColumnName("heirloom_points"); + + b.Property("IsDonor") + .HasColumnType("boolean") + .HasColumnName("is_donor"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Note") + .IsRequired() + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("Platform") + .HasColumnType("platform") + .HasColumnName("platform"); + + b.Property("PlatformUserId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("platform_user_id"); + + b.Property("Region") + .HasColumnType("region") + .HasColumnName("region"); + + b.Property("Role") + .HasColumnType("role") + .HasColumnName("role"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("updated_at"); + + b.Property("Version") + .IsConcurrencyToken() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("xid") + .HasColumnName("xmin"); + + b.HasKey("Id") + .HasName("pk_users"); + + b.HasIndex("ActiveCharacterId") + .IsUnique() + .HasDatabaseName("ix_users_active_character_id"); + + b.HasIndex("Platform", "PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_users_platform_platform_user_id"); + + b.ToTable("users", (string)null); + }); + + modelBuilder.Entity("ItemTheme", b => + { + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("ThemesId") + .HasColumnType("integer") + .HasColumnName("themes_id"); + + b.HasKey("ItemId", "ThemesId") + .HasName("pk_item_theme"); + + b.HasIndex("ThemesId") + .HasDatabaseName("ix_item_theme_themes_id"); + + b.ToTable("item_theme", (string)null); + }); + + modelBuilder.Entity("BattleParticipantStatistic", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany() + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participant_statistic_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleParticipant", "Participant") + .WithOne("Statistic") + .HasForeignKey("BattleParticipantStatistic", "ParticipantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participant_statistic_battle_participants_participan"); + + b.Navigation("Battle"); + + b.Navigation("Participant"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_activity_logs_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLogMetadata", b => + { + b.HasOne("Crpg.Domain.Entities.ActivityLogs.ActivityLog", null) + .WithMany("Metadata") + .HasForeignKey("ActivityLogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_activity_log_metadata_activity_logs_activity_log_id"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighter", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("Fighters") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighters_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .HasConstraintName("fk_battle_fighters_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") + .WithMany() + .HasForeignKey("SettlementId") + .HasConstraintName("fk_battle_fighters_settlements_settlement_id"); + + b.Navigation("Battle"); + + b.Navigation("Party"); + + b.Navigation("Settlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleFighterApplication", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("FighterApplications") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighter_applications_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_fighter_applications_parties_party_id"); + + b.Navigation("Battle"); + + b.Navigation("Party"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("MercenaryApplications") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_mercenary_applications_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_mercenary_applications_characters_character_id"); + + b.Navigation("Battle"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("Participants") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_battles_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleFighter", "CaptainFighter") + .WithMany() + .HasForeignKey("CaptainFighterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_battle_fighters_captain_fighter_id"); + + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany() + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_participants_characters_character_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.BattleMercenaryApplication", "MercenaryApplication") + .WithMany() + .HasForeignKey("MercenaryApplicationId") + .HasConstraintName("fk_battle_participants_battle_mercenary_applications_mercenary"); + + b.Navigation("Battle"); + + b.Navigation("CaptainFighter"); + + b.Navigation("Character"); + + b.Navigation("MercenaryApplication"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleSideBriefing", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") + .WithMany("SideBriefings") + .HasForeignKey("BattleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_battle_side_briefings_battles_battle_id"); + + b.Navigation("Battle"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Characters") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_characters_users_user_id"); + + b.OwnsOne("Crpg.Domain.Entities.Characters.CharacterCharacteristics", "Characteristics", b1 => + { + b1.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b1.HasKey("CharacterId"); + + b1.ToTable("characters"); + + b1.WithOwner() + .HasForeignKey("CharacterId") + .HasConstraintName("fk_characters_characters_id"); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterAttributes", "Attributes", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Agility") + .HasColumnType("integer") + .HasColumnName("agility"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("attribute_points"); + + b2.Property("Strength") + .HasColumnType("integer") + .HasColumnName("strength"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterSkills", "Skills", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Athletics") + .HasColumnType("integer") + .HasColumnName("athletics"); + + b2.Property("IronFlesh") + .HasColumnType("integer") + .HasColumnName("iron_flesh"); + + b2.Property("MountedArchery") + .HasColumnType("integer") + .HasColumnName("mounted_archery"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("skill_points"); + + b2.Property("PowerDraw") + .HasColumnType("integer") + .HasColumnName("power_draw"); + + b2.Property("PowerStrike") + .HasColumnType("integer") + .HasColumnName("power_strike"); + + b2.Property("PowerThrow") + .HasColumnType("integer") + .HasColumnName("power_throw"); + + b2.Property("Riding") + .HasColumnType("integer") + .HasColumnName("riding"); + + b2.Property("Shield") + .HasColumnType("integer") + .HasColumnName("shield"); + + b2.Property("WeaponMaster") + .HasColumnType("integer") + .HasColumnName("weapon_master"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterWeaponProficiencies", "WeaponProficiencies", b2 => + { + b2.Property("CharacterCharacteristicsCharacterId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("Bow") + .HasColumnType("integer") + .HasColumnName("bow"); + + b2.Property("Crossbow") + .HasColumnType("integer") + .HasColumnName("crossbow"); + + b2.Property("OneHanded") + .HasColumnType("integer") + .HasColumnName("one_handed"); + + b2.Property("Points") + .HasColumnType("integer") + .HasColumnName("weapon_proficiency_points"); + + b2.Property("Polearm") + .HasColumnType("integer") + .HasColumnName("polearm"); + + b2.Property("Throwing") + .HasColumnType("integer") + .HasColumnName("throwing"); + + b2.Property("TwoHanded") + .HasColumnType("integer") + .HasColumnName("two_handed"); + + b2.HasKey("CharacterCharacteristicsCharacterId"); + + b2.ToTable("characters"); + + b2.WithOwner() + .HasForeignKey("CharacterCharacteristicsCharacterId") + .HasConstraintName("fk_characters_characters_id"); + }); + + b1.Navigation("Attributes") + .IsRequired(); + + b1.Navigation("Skills") + .IsRequired(); + + b1.Navigation("WeaponProficiencies") + .IsRequired(); + }); + + b.OwnsMany("Crpg.Domain.Entities.Characters.CharacterStatistics", "Statistics", b1 => + { + b1.Property("CharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b1.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b1.Property("Id")); + + b1.Property("Assists") + .HasColumnType("integer") + .HasColumnName("assists"); + + b1.Property("Deaths") + .HasColumnType("integer") + .HasColumnName("deaths"); + + b1.Property("GameMode") + .HasColumnType("game_mode") + .HasColumnName("game_mode"); + + b1.Property("Kills") + .HasColumnType("integer") + .HasColumnName("kills"); + + b1.Property("PlayTime") + .HasColumnType("interval") + .HasColumnName("play_time"); + + b1.HasKey("CharacterId", "Id") + .HasName("pk_character_statistics"); + + b1.ToTable("character_statistics", (string)null); + + b1.WithOwner("Character") + .HasForeignKey("CharacterId") + .HasConstraintName("fk_character_statistics_characters_character_id"); + + b1.OwnsOne("Crpg.Domain.Entities.Characters.CharacterRating", "Rating", b2 => + { + b2.Property("CharacterStatisticsCharacterId") + .HasColumnType("integer") + .HasColumnName("character_id"); + + b2.Property("CharacterStatisticsId") + .HasColumnType("integer") + .HasColumnName("id"); + + b2.Property("CompetitiveValue") + .HasColumnType("real") + .HasColumnName("competitive_rating"); + + b2.Property("Deviation") + .HasColumnType("real") + .HasColumnName("rating_deviation"); + + b2.Property("Value") + .HasColumnType("real") + .HasColumnName("rating"); + + b2.Property("Volatility") + .HasColumnType("real") + .HasColumnName("rating_volatility"); + + b2.HasKey("CharacterStatisticsCharacterId", "CharacterStatisticsId"); + + b2.ToTable("character_statistics"); + + b2.WithOwner() + .HasForeignKey("CharacterStatisticsCharacterId", "CharacterStatisticsId") + .HasConstraintName("fk_character_statistics_character_statistics_character_id_id"); + }); + + b1.Navigation("Character"); + + b1.Navigation("Rating") + .IsRequired(); + }); + + b.Navigation("Characteristics") + .IsRequired(); + + b.Navigation("Statistics"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("ArmoryBorrowedItems") + .HasForeignKey("BorrowerClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clans_borrower_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Borrower") + .WithMany("ArmoryBorrowedItems") + .HasForeignKey("BorrowerUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clan_members_borrower_user_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("ClanArmoryBorrowedItem") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_user_items_user_item_id"); + + b.HasOne("Crpg.Domain.Entities.Items.ClanArmoryItem", "ArmoryItem") + .WithOne("BorrowedItem") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanArmoryBorrowedItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_borrowed_items_clan_armory_items_user_item_id"); + + b.Navigation("ArmoryItem"); + + b.Navigation("Borrower"); + + b.Navigation("Clan"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanInvitation", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("Invitations") + .HasForeignKey("ClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_clans_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "Invitee") + .WithMany() + .HasForeignKey("InviteeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_users_invitee_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "Inviter") + .WithMany() + .HasForeignKey("InviterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_invitations_users_inviter_id"); + + b.Navigation("Clan"); + + b.Navigation("Invitee"); + + b.Navigation("Inviter"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("Members") + .HasForeignKey("ClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_members_clans_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithOne("ClanMembership") + .HasForeignKey("Crpg.Domain.Entities.Clans.ClanMember", "UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_members_users_user_id"); + + b.Navigation("Clan"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.GameEvents.GameEvent", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .HasConstraintName("fk_game_events_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.HasOne("Crpg.Domain.Entities.Clans.Clan", "Clan") + .WithMany("ArmoryItems") + .HasForeignKey("LenderClanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_clans_lender_clan_id"); + + b.HasOne("Crpg.Domain.Entities.Clans.ClanMember", "Lender") + .WithMany("ArmoryItems") + .HasForeignKey("LenderUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_clan_members_lender_user_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("ClanArmoryItem") + .HasForeignKey("Crpg.Domain.Entities.Items.ClanArmoryItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clan_armory_items_user_items_user_item_id"); + + b.Navigation("Clan"); + + b.Navigation("Lender"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.EquippedItem", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithMany("EquippedItems") + .HasForeignKey("CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_equipped_items_characters_character_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithMany("EquippedItems") + .HasForeignKey("UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_equipped_items_user_items_user_item_id"); + + b.Navigation("Character"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "PrimaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("primary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("primary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("primary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("primary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("primary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("primary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("primary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("primary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("primary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("primary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("primary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("primary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("primary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("primary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("primary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("primary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "SecondaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("secondary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("secondary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("secondary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("secondary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("secondary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("secondary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("secondary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("secondary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("secondary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("secondary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("secondary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("secondary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("secondary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("secondary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemWeaponComponent", "TertiaryWeapon", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("Accuracy") + .HasColumnType("integer") + .HasColumnName("tertiary_accuracy"); + + b1.Property("Balance") + .HasColumnType("real") + .HasColumnName("tertiary_balance"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("tertiary_body_armor"); + + b1.Property("Class") + .HasColumnType("weapon_class") + .HasColumnName("tertiary_class"); + + b1.Property("Flags") + .HasColumnType("bigint") + .HasColumnName("tertiary_flags"); + + b1.Property("Handling") + .HasColumnType("integer") + .HasColumnName("tertiary_handling"); + + b1.Property("ItemUsage") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tertiary_weapon_item_usage"); + + b1.Property("Length") + .HasColumnType("integer") + .HasColumnName("tertiary_length"); + + b1.Property("MissileSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_missile_speed"); + + b1.Property("StackAmount") + .HasColumnType("integer") + .HasColumnName("tertiary_stack_amount"); + + b1.Property("SwingDamage") + .HasColumnType("integer") + .HasColumnName("tertiary_swing_damage"); + + b1.Property("SwingDamageType") + .HasColumnType("damage_type") + .HasColumnName("tertiary_swing_damage_type"); + + b1.Property("SwingSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_swing_speed"); + + b1.Property("ThrustDamage") + .HasColumnType("integer") + .HasColumnName("tertiary_thrust_damage"); + + b1.Property("ThrustDamageType") + .HasColumnType("damage_type") + .HasColumnName("tertiary_thrust_damage_type"); + + b1.Property("ThrustSpeed") + .HasColumnType("integer") + .HasColumnName("tertiary_thrust_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemArmorComponent", "Armor", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("ArmArmor") + .HasColumnType("integer") + .HasColumnName("armor_arm"); + + b1.Property("BodyArmor") + .HasColumnType("integer") + .HasColumnName("armor_body"); + + b1.Property("FamilyType") + .HasColumnType("integer") + .HasColumnName("armor_family_type"); + + b1.Property("HeadArmor") + .HasColumnType("integer") + .HasColumnName("armor_head"); + + b1.Property("LegArmor") + .HasColumnType("integer") + .HasColumnName("armor_leg"); + + b1.Property("MaterialType") + .HasColumnType("integer") + .HasColumnName("armor_material_type"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.OwnsOne("Crpg.Domain.Entities.Items.ItemMountComponent", "Mount", b1 => + { + b1.Property("ItemId") + .HasColumnType("text") + .HasColumnName("id"); + + b1.Property("BodyLength") + .HasColumnType("integer") + .HasColumnName("mount_body_length"); + + b1.Property("ChargeDamage") + .HasColumnType("integer") + .HasColumnName("mount_charge_damage"); + + b1.Property("FamilyType") + .HasColumnType("integer") + .HasColumnName("mount_family_type"); + + b1.Property("HitPoints") + .HasColumnType("integer") + .HasColumnName("mount_hit_points"); + + b1.Property("Maneuver") + .HasColumnType("integer") + .HasColumnName("mount_maneuver"); + + b1.Property("Speed") + .HasColumnType("integer") + .HasColumnName("mount_speed"); + + b1.HasKey("ItemId"); + + b1.ToTable("items"); + + b1.WithOwner() + .HasForeignKey("ItemId") + .HasConstraintName("fk_items_items_id"); + }); + + b.Navigation("Armor"); + + b.Navigation("Mount"); + + b.Navigation("PrimaryWeapon"); + + b.Navigation("SecondaryWeapon"); + + b.Navigation("TertiaryWeapon"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ItemStack", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_stacks_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany("Items") + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.PartyTransferOffer", "PartyTransferOffer") + .WithMany("Items") + .HasForeignKey("PartyTransferOfferId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_party_transfer_offers_party_transfer_offer_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "Settlement") + .WithMany("Items") + .HasForeignKey("SettlementId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_item_stacks_settlements_settlement_id"); + + b.Navigation("Item"); + + b.Navigation("Party"); + + b.Navigation("PartyTransferOffer"); + + b.Navigation("Settlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.PersonalItem", b => + { + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithOne("PersonalItem") + .HasForeignKey("Crpg.Domain.Entities.Items.PersonalItem", "UserItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_personal_items_user_items_user_item_id"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany("UserItems") + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_items_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Items") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_items_users_user_id"); + + b.Navigation("Item"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("ItemPresets") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_item_presets_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPresetSlot", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_user_item_preset_slots_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItemPreset", "UserItemPreset") + .WithMany("Slots") + .HasForeignKey("UserItemPresetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_item_preset_slots_user_item_presets_user_item_preset_id"); + + b.Navigation("Item"); + + b.Navigation("UserItemPreset"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Limitations.CharacterLimitations", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "Character") + .WithOne("Limitations") + .HasForeignKey("Crpg.Domain.Entities.Limitations.CharacterLimitations", "CharacterId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_character_limitations_characters_character_id"); + + b.Navigation("Character"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "Seller") + .WithMany("MarketplaceListings") + .HasForeignKey("SellerId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_marketplace_listings_users_seller_id"); + + b.Navigation("Seller"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListingAsset", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", "Item") + .WithMany() + .HasForeignKey("ItemId") + .HasConstraintName("fk_marketplace_listing_assets_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Marketplace.MarketplaceListing", "MarketplaceListing") + .WithMany("Assets") + .HasForeignKey("MarketplaceListingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_marketplace_listing_assets_marketplace_listings_marketplace"); + + b.HasOne("Crpg.Domain.Entities.Items.UserItem", "UserItem") + .WithMany("MarketplaceListingAssets") + .HasForeignKey("UserItemId") + .OnDelete(DeleteBehavior.Restrict) + .HasConstraintName("fk_marketplace_listing_assets_user_items_user_item_id"); + + b.Navigation("Item"); + + b.Navigation("MarketplaceListing"); + + b.Navigation("UserItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany("Notifications") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_notifications_users_user_id"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotificationMetadata", b => + { + b.HasOne("Crpg.Domain.Entities.Notifications.UserNotification", null) + .WithMany("Metadata") + .HasForeignKey("UserNotificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_notification_metadata_user_notifications_user_notifica"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "CurrentBattle") + .WithMany() + .HasForeignKey("CurrentBattleId") + .HasConstraintName("fk_parties_battles_current_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "CurrentParty") + .WithMany() + .HasForeignKey("CurrentPartyId") + .HasConstraintName("fk_parties_parties_current_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "CurrentSettlement") + .WithMany() + .HasForeignKey("CurrentSettlementId") + .HasConstraintName("fk_parties_settlements_current_settlement_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithOne("Party") + .HasForeignKey("Crpg.Domain.Entities.Parties.Party", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_parties_users_id"); + + b.Navigation("CurrentBattle"); + + b.Navigation("CurrentParty"); + + b.Navigation("CurrentSettlement"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyOrder", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany("Orders") + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_orders_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Battles.Battle", "TargetedBattle") + .WithMany() + .HasForeignKey("TargetedBattleId") + .HasConstraintName("fk_party_orders_battles_targeted_battle_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetedParty") + .WithMany() + .HasForeignKey("TargetedPartyId") + .HasConstraintName("fk_party_orders_parties_targeted_party_id"); + + b.HasOne("Crpg.Domain.Entities.Settlements.Settlement", "TargetedSettlement") + .WithMany() + .HasForeignKey("TargetedSettlementId") + .HasConstraintName("fk_party_orders_settlements_targeted_settlement_id"); + + b.Navigation("Party"); + + b.Navigation("TargetedBattle"); + + b.Navigation("TargetedParty"); + + b.Navigation("TargetedSettlement"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Party") + .WithMany() + .HasForeignKey("PartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_transfer_offers_parties_party_id"); + + b.HasOne("Crpg.Domain.Entities.Parties.Party", "TargetParty") + .WithMany() + .HasForeignKey("TargetPartyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_party_transfer_offers_parties_target_party_id"); + + b.Navigation("Party"); + + b.Navigation("TargetParty"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.UserQuest", b => + { + b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") + .WithMany() + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_user_quests_quest_definitions_quest_definition_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_user_quests_users_user_id"); + + b.Navigation("QuestDefinition"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Quests.WeeklyQuestAssignment", b => + { + b.HasOne("Crpg.Domain.Entities.Quests.QuestDefinition", "QuestDefinition") + .WithMany() + .HasForeignKey("QuestDefinitionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired() + .HasConstraintName("fk_weekly_quest_assignments_quest_definitions_quest_definition"); + + b.Navigation("QuestDefinition"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Restrictions.Restriction", b => + { + b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedByUser") + .WithMany() + .HasForeignKey("RestrictedByUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_restrictions_users_restricted_by_user_id"); + + b.HasOne("Crpg.Domain.Entities.Users.User", "RestrictedUser") + .WithMany("Restrictions") + .HasForeignKey("RestrictedUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_restrictions_users_restricted_user_id"); + + b.Navigation("RestrictedByUser"); + + b.Navigation("RestrictedUser"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.HasOne("Crpg.Domain.Entities.Parties.Party", "Owner") + .WithMany("OwnedSettlements") + .HasForeignKey("OwnerId") + .HasConstraintName("fk_settlements_parties_owner_id"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Themes.ThemeEvent", b => + { + b.HasOne("Crpg.Domain.Entities.Themes.Theme", "EventTheme") + .WithMany() + .HasForeignKey("EventThemeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_theme_events_themes_event_theme_id"); + + b.Navigation("EventTheme"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.HasOne("Crpg.Domain.Entities.Characters.Character", "ActiveCharacter") + .WithOne() + .HasForeignKey("Crpg.Domain.Entities.Users.User", "ActiveCharacterId") + .HasConstraintName("fk_users_characters_active_character_id"); + + b.Navigation("ActiveCharacter"); + }); + + modelBuilder.Entity("ItemTheme", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_theme_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Themes.Theme", null) + .WithMany() + .HasForeignKey("ThemesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_theme_themes_themes_id"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => + { + b.Navigation("Metadata"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.Battle", b => + { + b.Navigation("FighterApplications"); + + b.Navigation("Fighters"); + + b.Navigation("MercenaryApplications"); + + b.Navigation("Participants"); + + b.Navigation("SideBriefings"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Battles.BattleParticipant", b => + { + b.Navigation("Statistic"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Characters.Character", b => + { + b.Navigation("EquippedItems"); + + b.Navigation("Limitations"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.Clan", b => + { + b.Navigation("ArmoryBorrowedItems"); + + b.Navigation("ArmoryItems"); + + b.Navigation("Invitations"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Clans.ClanMember", b => + { + b.Navigation("ArmoryBorrowedItems"); + + b.Navigation("ArmoryItems"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.ClanArmoryItem", b => + { + b.Navigation("BorrowedItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.Item", b => + { + b.Navigation("UserItems"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItem", b => + { + b.Navigation("ClanArmoryBorrowedItem"); + + b.Navigation("ClanArmoryItem"); + + b.Navigation("EquippedItems"); + + b.Navigation("MarketplaceListingAssets"); + + b.Navigation("PersonalItem"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Items.UserItemPreset", b => + { + b.Navigation("Slots"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Marketplace.MarketplaceListing", b => + { + b.Navigation("Assets"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Notifications.UserNotification", b => + { + b.Navigation("Metadata"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.Party", b => + { + b.Navigation("Items"); + + b.Navigation("Orders"); + + b.Navigation("OwnedSettlements"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Parties.PartyTransferOffer", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Settlements.Settlement", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("Crpg.Domain.Entities.Users.User", b => + { + b.Navigation("Characters"); + + b.Navigation("ClanMembership"); + + b.Navigation("ItemPresets"); + + b.Navigation("Items"); + + b.Navigation("MarketplaceListings"); + + b.Navigation("Notifications"); + + b.Navigation("Party"); + + b.Navigation("Restrictions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.cs b/src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.cs new file mode 100644 index 000000000..350fb6c5d --- /dev/null +++ b/src/Persistence/Migrations/20260615113350_FixItemAndThemeRelation.cs @@ -0,0 +1,50 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Crpg.Persistence.Migrations +{ + /// + public partial class FixItemAndThemeRelation : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "item_theme", + columns: table => new + { + item_id = table.Column(type: "text", nullable: false), + themes_id = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_item_theme", x => new { x.item_id, x.themes_id }); + table.ForeignKey( + name: "fk_item_theme_items_item_id", + column: x => x.item_id, + principalTable: "items", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "fk_item_theme_themes_themes_id", + column: x => x.themes_id, + principalTable: "themes", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_item_theme_themes_id", + table: "item_theme", + column: "themes_id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "item_theme"); + } + } +} diff --git a/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs b/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs index 235251791..f5f76e5d8 100644 --- a/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs +++ b/src/Persistence/Migrations/CrpgDbContextModelSnapshot.cs @@ -1947,6 +1947,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("users", (string)null); }); + modelBuilder.Entity("ItemTheme", b => + { + b.Property("ItemId") + .HasColumnType("text") + .HasColumnName("item_id"); + + b.Property("ThemesId") + .HasColumnType("integer") + .HasColumnName("themes_id"); + + b.HasKey("ItemId", "ThemesId") + .HasName("pk_item_theme"); + + b.HasIndex("ThemesId") + .HasDatabaseName("ix_item_theme_themes_id"); + + b.ToTable("item_theme", (string)null); + }); + modelBuilder.Entity("BattleParticipantStatistic", b => { b.HasOne("Crpg.Domain.Entities.Battles.Battle", "Battle") @@ -3185,6 +3204,23 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("ActiveCharacter"); }); + modelBuilder.Entity("ItemTheme", b => + { + b.HasOne("Crpg.Domain.Entities.Items.Item", null) + .WithMany() + .HasForeignKey("ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_theme_items_item_id"); + + b.HasOne("Crpg.Domain.Entities.Themes.Theme", null) + .WithMany() + .HasForeignKey("ThemesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_item_theme_themes_themes_id"); + }); + modelBuilder.Entity("Crpg.Domain.Entities.ActivityLogs.ActivityLog", b => { b.Navigation("Metadata"); From e92231271f27a9518dc720bb539040db9fbfba2a Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Mon, 15 Jun 2026 13:53:16 +0200 Subject: [PATCH 11/38] Fixes item themes data seeding --- .../System/Commands/SeedDataCommand.cs | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/Application/System/Commands/SeedDataCommand.cs b/src/Application/System/Commands/SeedDataCommand.cs index ddee08a06..71f67ba3c 100644 --- a/src/Application/System/Commands/SeedDataCommand.cs +++ b/src/Application/System/Commands/SeedDataCommand.cs @@ -650,6 +650,18 @@ private async Task AddDevelopmentData(CancellationToken cancellationToken) Avatar = new Uri( "https://avatars.akamai.steamstatic.com/d51d5155b1a564421c0b3fd5fb7eed7c4474e73d_full.jpg"), }; + User zorak = new() + { + PlatformUserId = "76561197992612019", + Platform = Platform.Steam, + Name = "Dr. Hax (Zorak)", + Role = Role.Admin, + Gold = 1000000, + HeirloomPoints = 12, + ExperienceMultiplier = 1.09f, + Avatar = new Uri( + "https://avatars.fastly.steamstatic.com/a5e502265410b95711111316c47243dfb2993fbf_full.jpg"), + }; User[] newUsers = { @@ -659,7 +671,7 @@ private async Task AddDevelopmentData(CancellationToken cancellationToken) ajroselle, skrael, bedo, lambic, sanasar, vlad007, canp0g, shark, noobAmphetamine, mundete, aroyFalconer, insanitoid, scarface, xDem, disorot, ace, sagar, greenShadow, hannibaru, drexx, xarosh, tipsyToby, localAlpha, alex, kedrynFuel, luqero, ilya, eztli, telesto, kypak, devoidDragon, - krog, thradok, kinngrimm, kadse, ladoea, enfiol, + krog, thradok, kinngrimm, kadse, ladoea, enfiol, zorak, }; var existingUsers = await _db.Users.ToDictionaryAsync(u => (u.Platform, u.PlatformUserId)); @@ -1326,6 +1338,19 @@ private async Task AddDevelopmentData(CancellationToken cancellationToken) Skills = new CharacterSkills { Points = 100 }, }, }; + Character zorakCharacter = new() + { + User = zorak, + Name = "Zorak", + Level = 33, + Generation = 1, + Experience = _experienceTable.GetExperienceForLevel(33), + Characteristics = new CharacterCharacteristics + { + Attributes = new CharacterAttributes { Points = 100 }, + Skills = new CharacterSkills { Points = 100 }, + }, + }; Character falcomCharacter0 = new() { User = falcom, Name = falcom.Name, }; Character victorhh888Character0 = new() { User = victorhh888, Name = victorhh888.Name, }; Character sellkaCharacter0 = new() { User = sellka, Name = sellka.Name, }; @@ -1337,7 +1362,7 @@ private async Task AddDevelopmentData(CancellationToken cancellationToken) takeoCharacter0, takeoCharacter1, takeoCharacter2, namidakaCharacter0, peekyCharacter0, orleCharacter0, orleCharacter1, orleCharacter2, orle2Character0, droobCharacter0, vickCharacter0, vickCharacter1, falcomCharacter0, victorhh888Character0, sellkaCharacter0, krogCharacter0, - kadseCharacter0, noobAmphetamineCharacter0, baronCyborgCharacter0, ladoeaCharacter0, + kadseCharacter0, noobAmphetamineCharacter0, baronCyborgCharacter0, ladoeaCharacter0, zorakCharacter, }; var existingCharacters = await _db.Characters.ToDictionaryAsync(c => c.Name); @@ -2788,10 +2813,12 @@ private async Task CreateOrUpdateItems(CancellationToken cancellationToken) .Include(i => i.Themes) .AsSplitQuery() .ToDictionaryAsync(i => i.Id, cancellationToken); + var dbThemesById = await _db.Themes.ToDictionaryAsync(t => t.Id, cancellationToken); + var themes = new Dictionary(dbThemesById); foreach (ItemCreation item in itemsById.Values) { - Item itemToCreate = ItemCreationToItem(item); + Item itemToCreate = ItemCreationToItem(item, themes); CreateOrUpdateItem(dbItemsById, itemToCreate); } @@ -2828,6 +2855,11 @@ private void CreateOrUpdateItem(Dictionary dbItemsByMbId, Item ite dbItem.PrimaryWeapon = item.PrimaryWeapon; dbItem.SecondaryWeapon = item.SecondaryWeapon; dbItem.TertiaryWeapon = item.TertiaryWeapon; + dbItem.Themes.Clear(); + if (item.Themes != null) + { + dbItem.Themes.AddRange(item.Themes); + } } else { @@ -2850,7 +2882,7 @@ private void CreateOrUpdateItem(Dictionary dbItemsByMbId, Item ite } } - private Item ItemCreationToItem(ItemCreation item) + private Item ItemCreationToItem(ItemCreation item, Dictionary themes) { Item res = new() { @@ -2866,6 +2898,7 @@ private Item ItemCreationToItem(ItemCreation item) Requirement = item.Requirement, Flags = item.Flags, Enabled = true, + Themes = new(), }; if (item.Armor != null) @@ -2909,14 +2942,34 @@ private Item ItemCreationToItem(ItemCreation item) res.TertiaryWeapon = IteamWeaponComponentFromViewModel(item.Weapons[2]); } - if (item.Themes != null) + if (item.Themes != null && item.Themes.Count > 0) { - res.Themes = item.Themes.Select(i => new Theme(i.Name) { Id = i.Id }).ToList(); + res.Themes.AddRange(CreateThemesForItem(item, themes)); } return res; } + private static List CreateThemesForItem(ItemCreation item, Dictionary themeInstances) + { + var themes = new List(); + foreach (var themeVm in item.Themes) + { + if (themeInstances.TryGetValue(themeVm.Id, out var existingTheme)) + { + themes.Add(existingTheme); + } + else + { + var newTheme = new Theme(themeVm.Name) { Id = themeVm.Id }; + themeInstances[themeVm.Id] = newTheme; + themes.Add(newTheme); + } + } + + return themes; + } + private ItemWeaponComponent IteamWeaponComponentFromViewModel(ItemWeaponComponentViewModel weaponComponent) { return new() From 163ec005f06d1f874160c21397be158da032746e Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Mon, 15 Jun 2026 16:15:48 +0200 Subject: [PATCH 12/38] Adds Theme Event handling to crpg client and server --- src/Module.Server/Api/HttpCrpgClient.cs | 4 +- src/Module.Server/Api/ICrpgClient.cs | 2 +- .../Api/Models/Themes/ThemeEvent.cs | 2 + src/Module.Server/Api/StubCrpgClient.cs | 2 +- src/Module.Server/Rewards/CrpgRewardClient.cs | 9 ++ src/Module.Server/Rewards/CrpgRewardServer.cs | 96 +++++++++++++++++-- .../Rewards/CrpgRewardThemeEvent.cs | 27 ++++++ src/WebApi/Controllers/GamesController.cs | 11 ++- 8 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 src/Module.Server/Rewards/CrpgRewardThemeEvent.cs diff --git a/src/Module.Server/Api/HttpCrpgClient.cs b/src/Module.Server/Api/HttpCrpgClient.cs index 61dd4d63d..59c8e4d3a 100644 --- a/src/Module.Server/Api/HttpCrpgClient.cs +++ b/src/Module.Server/Api/HttpCrpgClient.cs @@ -117,9 +117,9 @@ public Task CreateGameEventsAsync(CrpgGameEventsCreateRequest req, CancellationT return Post("games/game-events", req, cancellationToken); } - public Task>> GetActiveThemeEvents(CancellationToken cancellationToken = default) + public Task>> GetActiveThemeEventsAsync(CancellationToken cancellationToken = default) { - return Get>("games/themes/events/active", null, cancellationToken); + return Get>("games/theme-events/active", null, cancellationToken); } public void Dispose() => _httpClient.Dispose(); diff --git a/src/Module.Server/Api/ICrpgClient.cs b/src/Module.Server/Api/ICrpgClient.cs index 2c80369db..fe764e447 100644 --- a/src/Module.Server/Api/ICrpgClient.cs +++ b/src/Module.Server/Api/ICrpgClient.cs @@ -28,5 +28,5 @@ Task> RestrictUserAsync(CrpgRestrictionRequest req, Task CreateGameEventsAsync(CrpgGameEventsCreateRequest req, CancellationToken cancellationToken = default); - Task>> GetActiveThemeEvents(CancellationToken cancellationToken = default); + Task>> GetActiveThemeEventsAsync(CancellationToken cancellationToken = default); } diff --git a/src/Module.Server/Api/Models/Themes/ThemeEvent.cs b/src/Module.Server/Api/Models/Themes/ThemeEvent.cs index 08b41de8d..a30b6c827 100644 --- a/src/Module.Server/Api/Models/Themes/ThemeEvent.cs +++ b/src/Module.Server/Api/Models/Themes/ThemeEvent.cs @@ -19,4 +19,6 @@ internal class ThemeEvent public int MinumumRequiredEquipmentSlotsMatchingTheme { get; set; } public Theme EventTheme { get; set; } = default!; + + public List EligibleItemIds { get; set; } = new(); } diff --git a/src/Module.Server/Api/StubCrpgClient.cs b/src/Module.Server/Api/StubCrpgClient.cs index 7a9b11a75..d8e3cde8f 100644 --- a/src/Module.Server/Api/StubCrpgClient.cs +++ b/src/Module.Server/Api/StubCrpgClient.cs @@ -132,7 +132,7 @@ public Task CreateGameEventsAsync(CrpgGameEventsCreateRequest req, CancellationT return Task.CompletedTask; } - public Task>> GetActiveThemeEvents(CancellationToken cancellationToken = default) + public Task>> GetActiveThemeEventsAsync(CancellationToken cancellationToken = default) { return Task.FromResult(new CrpgResult> { Data = new List() }); } diff --git a/src/Module.Server/Rewards/CrpgRewardClient.cs b/src/Module.Server/Rewards/CrpgRewardClient.cs index 5e09df04b..207c8631e 100644 --- a/src/Module.Server/Rewards/CrpgRewardClient.cs +++ b/src/Module.Server/Rewards/CrpgRewardClient.cs @@ -39,6 +39,7 @@ protected override void AddRemoveMessageHandlers(GameNetwork.NetworkMessageHandl registerer.Register(HandleRewardUser); registerer.Register(HandleRewardError); registerer.Register(HandleRewardHappyHour); + registerer.Register(HandleRewardThemeEvent); } private void HandleRewardUser(CrpgRewardUser message) @@ -142,4 +143,12 @@ private void HandleRewardHappyHour(CrpgRewardHappyHour message) : new TextObject("{=KoqNpPLa}Happy hours ended!"); InformationManager.AddSystemNotification(textObject.ToString()); } + + private void HandleRewardThemeEvent(CrpgRewardThemeEvent message) + { + var textObject = new TextObject("{=wRAuUAkB}You've participated in a theme event and have been given extra rewards!"); + InformationManager.DisplayMessage( + new InformationMessage(textObject.ToString(), + new Color(46, 204, 113))); + } } diff --git a/src/Module.Server/Rewards/CrpgRewardServer.cs b/src/Module.Server/Rewards/CrpgRewardServer.cs index 1334b7d1b..f1ad049b8 100644 --- a/src/Module.Server/Rewards/CrpgRewardServer.cs +++ b/src/Module.Server/Rewards/CrpgRewardServer.cs @@ -1,15 +1,14 @@ using Crpg.Module.Api; using Crpg.Module.Api.Models; using Crpg.Module.Api.Models.Characters; -using Crpg.Module.Api.Models.Users; +using Crpg.Module.Api.Models.Items; +using Crpg.Module.Api.Models.Themes; using Crpg.Module.Common; -using Crpg.Module.Common.Network; using Crpg.Module.Modes.TrainingGround; using Crpg.Module.Modes.Warmup; using Crpg.Module.Rating; using TaleWorlds.Core; using TaleWorlds.Library; -using TaleWorlds.Localization; using TaleWorlds.MountAndBlade; using TaleWorlds.MountAndBlade.Diamond; using TaleWorlds.PlayerServices; @@ -273,6 +272,7 @@ public async Task UpdateCrpgUsersAsync( Dictionary> brokenItems = lowPopulationServer ? new() : GetBrokenItemsByCrpgUserId(networkPeers, durationUpkeep ?? durationRewarded); var compensationByCrpgUserId = _isTeamHitCompensationsEnabled ? CalculateCompensationByCrpgUserId(brokenItems) : new(); + var activeThemeEvents = await _crpgClient.GetActiveThemeEventsAsync(); foreach (NetworkCommunicator networkPeer in networkPeers) { var playerId = networkPeer.VirtualPlayer.Id; @@ -327,7 +327,7 @@ public async Task UpdateCrpgUsersAsync( bool isValorousPlayer = valorousPlayerIds.Contains(playerId); int compensationForCrpgUser = compensationByCrpgUserId.TryGetValue(crpgUserId, out int compensation) ? compensation : 0; SetRewardForConnectedPlayer(userUpdate, crpgPeer, durationRewarded, compensationForCrpgUser, isValorousPlayer, - defenderMultiplierGain, attackerMultiplierGain, constantMultiplier); + defenderMultiplierGain, attackerMultiplierGain, constantMultiplier, activeThemeEvents?.Data); if (brokenItems.TryGetValue(crpgUserId, out var userBrokenItems)) { @@ -339,7 +339,7 @@ public async Task UpdateCrpgUsersAsync( else if (crpgPeer.LastSpawnInfo != null && isPlayerInSpectator) // update spectators multiplier based on their previous team { SetRewardForConnectedPlayer(userUpdate, crpgPeer, 0, 0, false, - defenderMultiplierGain, attackerMultiplierGain, constantMultiplier); + defenderMultiplierGain, attackerMultiplierGain, constantMultiplier, activeThemeEvents?.Data); } userUpdates.Add(userUpdate); @@ -523,15 +523,25 @@ private void SetRewardForConnectedPlayer( bool isValorousPlayer, int defenderMultiplierGain, int attackerMultiplierGain, - int? constantMultiplier) + int? constantMultiplier, + List? activeThemeEvents) { float serverXpMultiplier = CrpgServerConfiguration.ServerExperienceMultiplier; + float goldMultiplier = 1.0f; serverXpMultiplier *= IsHappyHour() ? 1.5f : 1f; + + if (activeThemeEvents != null && activeThemeEvents.Count > 0) + { + var multipliers = GetActiveEventMultipliers(crpgPeer, activeThemeEvents); + serverXpMultiplier *= multipliers.expMultiplier; + goldMultiplier *= multipliers.goldMultiplier; + } + userUpdate.Reward = new CrpgUserReward { Experience = (int)(serverXpMultiplier * durationRewarded * (_constants.BaseExperienceGainPerSecond + crpgPeer.RewardMultiplier * _constants.MultipliedExperienceGainPerSecond)), - Gold = (int)(durationRewarded * (_constants.BaseGoldGainPerSecond + Gold = (int)(goldMultiplier * durationRewarded * (_constants.BaseGoldGainPerSecond + crpgPeer.RewardMultiplier * _constants.MultipliedGoldGainPerSecond) + compensationAmount), }; @@ -556,6 +566,78 @@ private void SetRewardForConnectedPlayer( } } + private static (float expMultiplier, float goldMultiplier) GetActiveEventMultipliers(CrpgPeer crpgPeer, List activeThemeEvents) + { + var playerEquippedItems = crpgPeer.User!.Character.EquippedItems; + float currentHighestEventExpMultiplier = 1.0f; + float currentHighestEventGoldMultiplier = 1.0f; + + foreach (var themeEvent in activeThemeEvents) + { + var playerSlotsWithEligibleItemEquipped = playerEquippedItems.Where(x => themeEvent.EligibleItemIds.Contains(x.UserItem.ItemId)).Select(x => x.Slot).ToList(); + bool playerIsEligibleForThemeEvent = PlayerIsEligibleForThemeEvent(themeEvent, playerSlotsWithEligibleItemEquipped); + if (playerIsEligibleForThemeEvent) + { + if (themeEvent.ExpMultiplier > currentHighestEventExpMultiplier) + { + currentHighestEventExpMultiplier = themeEvent.ExpMultiplier; + } + + if (themeEvent.GoldMultiplier > currentHighestEventGoldMultiplier) + { + currentHighestEventGoldMultiplier = themeEvent.GoldMultiplier; + } + } + } + + if (currentHighestEventExpMultiplier > 1.0f || currentHighestEventGoldMultiplier > 1.0f) + { + GameNetwork.BeginBroadcastModuleEvent(); + GameNetwork.WriteMessage(new CrpgRewardThemeEvent()); + GameNetwork.EndBroadcastModuleEvent(GameNetwork.EventBroadcastFlags.None); + } + + return (currentHighestEventExpMultiplier, currentHighestEventGoldMultiplier); + } + + private static bool PlayerIsEligibleForThemeEvent(ThemeEvent themeEvent, List playerSlotsWithEligibleItemEquipped) + { + return playerSlotsWithEligibleItemEquipped.Count >= themeEvent.MinumumRequiredEquipmentSlotsMatchingTheme && themeEvent.RequiredEquipmentSlotsMatchingTheme.All(r => playerSlotsWithEligibleItemEquipped.Contains(MapToThemeEquipmentSlot(r))); + } + + private static CrpgItemSlot MapToThemeEquipmentSlot(ThemeEquipmentSlot crpgItemSlot) + { + switch (crpgItemSlot) + { + case ThemeEquipmentSlot.Head: + return CrpgItemSlot.Head; + case ThemeEquipmentSlot.Shoulder: + return CrpgItemSlot.Shoulder; + case ThemeEquipmentSlot.Body: + return CrpgItemSlot.Body; + case ThemeEquipmentSlot.Hand: + return CrpgItemSlot.Hand; + case ThemeEquipmentSlot.Leg: + return CrpgItemSlot.Leg; + case ThemeEquipmentSlot.MountHarness: + return CrpgItemSlot.MountHarness; + case ThemeEquipmentSlot.Mount: + return CrpgItemSlot.Mount; + case ThemeEquipmentSlot.Weapon0: + return CrpgItemSlot.Weapon0; + case ThemeEquipmentSlot.Weapon1: + return CrpgItemSlot.Weapon1; + case ThemeEquipmentSlot.Weapon2: + return CrpgItemSlot.Weapon2; + case ThemeEquipmentSlot.Weapon3: + return CrpgItemSlot.Weapon3; + case ThemeEquipmentSlot.WeaponExtra: + return CrpgItemSlot.WeaponExtra; + default: + throw new ArgumentOutOfRangeException("Theme equipment slot did not exist on in character equipment slots."); + } + } + private bool IsHappyHour() { var happyHours = CrpgServerConfiguration.HappyHours; diff --git a/src/Module.Server/Rewards/CrpgRewardThemeEvent.cs b/src/Module.Server/Rewards/CrpgRewardThemeEvent.cs new file mode 100644 index 000000000..1815c34a7 --- /dev/null +++ b/src/Module.Server/Rewards/CrpgRewardThemeEvent.cs @@ -0,0 +1,27 @@ +using TaleWorlds.MountAndBlade; +using TaleWorlds.MountAndBlade.Network.Messages; + +namespace Crpg.Module.Rewards; + +[DefineGameNetworkMessageTypeForMod(GameNetworkMessageSendType.FromServer)] +internal sealed class CrpgRewardThemeEvent : GameNetworkMessage +{ + protected override void OnWrite() + { + } + + protected override bool OnRead() + { + return true; + } + + protected override MultiplayerMessageFilter OnGetLogFilter() + { + return MultiplayerMessageFilter.GameMode; + } + + protected override string OnGetLogFormat() + { + return nameof(CrpgRewardThemeEvent); + } +} diff --git a/src/WebApi/Controllers/GamesController.cs b/src/WebApi/Controllers/GamesController.cs index 694e10bd0..d53d4de96 100644 --- a/src/WebApi/Controllers/GamesController.cs +++ b/src/WebApi/Controllers/GamesController.cs @@ -7,6 +7,8 @@ using Crpg.Application.Games.Models; using Crpg.Application.Restrictions.Commands; using Crpg.Application.Restrictions.Models; +using Crpg.Application.Themes.Models; +using Crpg.Application.Themes.Queries; using Crpg.Domain.Entities; using Crpg.Domain.Entities.Servers; using Crpg.Domain.Entities.Users; @@ -90,5 +92,12 @@ public Task>> GetClan([FromRoute] int id) => public Task>> RestrictUser([FromBody] RestrictCommand req) { return ResultToActionAsync(Mediator.Send(req)); - } + } + + /// + /// Gets all active theme events. + /// + /// Ok. + [HttpGet("theme-events/active")] + public Task>>> GetActiveThemeEvents() => ResultToActionAsync(Mediator.Send(new GetActiveThemeEventsQuery())); } From 8499f4bb0f08d1be256d1530e02b2793c7ca9320 Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Mon, 15 Jun 2026 16:43:16 +0200 Subject: [PATCH 13/38] Adds themes when getting items --- src/Application/Items/Models/ItemViewModel.cs | 2 ++ src/Application/Items/Queries/GetItemsQuery.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/src/Application/Items/Models/ItemViewModel.cs b/src/Application/Items/Models/ItemViewModel.cs index c3a7a1329..346a2ac29 100644 --- a/src/Application/Items/Models/ItemViewModel.cs +++ b/src/Application/Items/Models/ItemViewModel.cs @@ -1,6 +1,7 @@ using System.Text.Json.Serialization; using AutoMapper; using Crpg.Application.Common.Mappings; +using Crpg.Application.Themes.Models; using Crpg.Domain.Entities; using Crpg.Domain.Entities.Items; @@ -26,6 +27,7 @@ public record ItemViewModel : IMapFrom public ItemMountComponentViewModel? Mount { get; init; } public IList Weapons { get; init; } = Array.Empty(); public bool Enabled { get; init; } + public IList Themes { get; init; } = Array.Empty(); public void Mapping(Profile profile) { diff --git a/src/Application/Items/Queries/GetItemsQuery.cs b/src/Application/Items/Queries/GetItemsQuery.cs index 503abb19d..cf1ae04ad 100644 --- a/src/Application/Items/Queries/GetItemsQuery.cs +++ b/src/Application/Items/Queries/GetItemsQuery.cs @@ -27,6 +27,7 @@ public async ValueTask>> Handle(GetItemsQuery req, C .OrderBy(i => i.Price) .Where(i => i.Enabled) .Where(i => i.Rank == 0) + .Include(i => i.Themes) .ToListAsync(cancellationToken); return new(_mapper.Map>(items)); From 968d9cea5ae7c7082bebd93922d73068a4c572ed Mon Sep 17 00:00:00 2001 From: Zorakoraz Date: Mon, 15 Jun 2026 22:44:48 +0200 Subject: [PATCH 14/38] Adds themes to items in the shop and player inventory --- .../Items/Queries/GetUserItemsQuery.cs | 1 + src/WebUI/app/assets/icons/theme.svg | 1 + .../item/CharacterInventoryItemCard.vue | 14 ++ .../app/components/item/ItemThemePills.vue | 42 ++++ .../app/components/item/detail/ItemDetail.vue | 7 + src/WebUI/app/models/item.ts | 8 + src/WebUI/app/pages/shop.vue | 7 +- .../services/item-search-service/indexator.ts | 3 +- src/WebUI/generated/api/index.ts | 4 +- src/WebUI/generated/api/sdk.gen.ts | 70 ++++++- src/WebUI/generated/api/transformers.gen.ts | 44 ++++- src/WebUI/generated/api/types.gen.ts | 182 +++++++++++++++++- 12 files changed, 369 insertions(+), 14 deletions(-) create mode 100644 src/WebUI/app/assets/icons/theme.svg create mode 100644 src/WebUI/app/components/item/ItemThemePills.vue diff --git a/src/Application/Items/Queries/GetUserItemsQuery.cs b/src/Application/Items/Queries/GetUserItemsQuery.cs index 4960deca0..82985ebea 100644 --- a/src/Application/Items/Queries/GetUserItemsQuery.cs +++ b/src/Application/Items/Queries/GetUserItemsQuery.cs @@ -21,6 +21,7 @@ public async ValueTask>> Handle(GetUserItemsQuer var userItems = await _db.UserItems .AsSplitQuery() .Include(ui => ui.Item) + .ThenInclude(i => i!.Themes) .Include(ui => ui.ClanArmoryItem) .ThenInclude(cai => cai!.Lender) .ThenInclude(cm => cm!.User) diff --git a/src/WebUI/app/assets/icons/theme.svg b/src/WebUI/app/assets/icons/theme.svg new file mode 100644 index 000000000..f88c3a90c --- /dev/null +++ b/src/WebUI/app/assets/icons/theme.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/WebUI/app/components/character/inventory/item/CharacterInventoryItemCard.vue b/src/WebUI/app/components/character/inventory/item/CharacterInventoryItemCard.vue index 7812d33c7..c45cc587d 100644 --- a/src/WebUI/app/components/character/inventory/item/CharacterInventoryItemCard.vue +++ b/src/WebUI/app/components/character/inventory/item/CharacterInventoryItemCard.vue @@ -67,6 +67,20 @@ const isNew = computed(() => !isGraceTimeExpired(getItemGraceTimeEnd(userItem))) label="new" size="sm" /> + + + + \ No newline at end of file + diff --git a/src/WebUI/app/components/admin/ThemeEventsTable.vue b/src/WebUI/app/components/admin/ThemeEventsTable.vue index e2bbb3509..7140578bb 100644 --- a/src/WebUI/app/components/admin/ThemeEventsTable.vue +++ b/src/WebUI/app/components/admin/ThemeEventsTable.vue @@ -16,8 +16,7 @@ const { t, d } = useI18n() const columns: TableColumn[] = [ - { accessorKey: 'id', header: () => t('theme.event.table.column.id') }, - { accessorKey: 'name', header: () => t('theme.event.table.column.name') }, + { accessorKey: 'name', header: () => t('theme.event.table.column.name') }, { id: 'theme', header: () => t('theme.event.table.column.theme'), diff --git a/src/WebUI/app/components/admin/ThemesTable.vue b/src/WebUI/app/components/admin/ThemesTable.vue index d867276c8..d5c886905 100644 --- a/src/WebUI/app/components/admin/ThemesTable.vue +++ b/src/WebUI/app/components/admin/ThemesTable.vue @@ -15,11 +15,10 @@ const { t } = useI18n() - const columns: TableColumn[] = [ - { accessorKey: 'id', header: () => t('theme.table.column.id') }, - { accessorKey: 'name', header: () => t('theme.table.column.name') }, - { id: 'actions' }, - ] + const columns: TableColumn[] = [ + { accessorKey: 'name', header: () => t('theme.table.column.name') }, + { id: 'actions' }, + ]