diff --git a/src/Dapr/GameServer.Host/_Imports.razor b/src/Dapr/GameServer.Host/_Imports.razor
index 4a18a36..61d3ed5 100644
--- a/src/Dapr/GameServer.Host/_Imports.razor
+++ b/src/Dapr/GameServer.Host/_Imports.razor
@@ -9,9 +9,6 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
-@using Blazored.Toast
-@using Blazored.Toast.Services
-
@using BlazorInputFile
@using MUnique.OpenMU.Web.Shared
diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 91b3051..5c2708a 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -6,7 +6,6 @@
-
diff --git a/src/Persistence/EntityFramework/EntityFrameworkContextBase.cs b/src/Persistence/EntityFramework/EntityFrameworkContextBase.cs
index ff16a74..459443d 100644
--- a/src/Persistence/EntityFramework/EntityFrameworkContextBase.cs
+++ b/src/Persistence/EntityFramework/EntityFrameworkContextBase.cs
@@ -92,69 +92,6 @@ internal class EntityFrameworkContextBase : IContext
}
}
- ///
- /// Determines whether the exception is a transient conflict caused by a concurrent entity mutation
- /// racing this save, and is therefore worth retrying.
- ///
- ///
The exception thrown by the save.
- ///
true if the save should be retried.
- private static bool IsTransientConcurrencyConflict(Exception exception)
- {
- // A concurrent entity mutation racing this save corrupts the change tracker mid-enumeration.
- // Depending on exactly where change detection was, it surfaces as one of several types - a
- // modified collection (InvalidOperationException), a transiently-null internal key
- // (ArgumentNullException/NullReferenceException), or an out-of-range index. All are transient:
- // the racing mutation is a single quick operation, so a bounded retry lands on a stable moment.
- // A genuinely persistent error of the same type is not masked - it rethrows once the retries
- // are exhausted. The deterministic serialization (per-player persistence lock) is the primary
- // guard; this retry only needs to absorb the rare, bursty sources that lock isn't held for.
- return exception is DbUpdateConcurrencyException
- or InvalidOperationException
- or ArgumentNullException
- or NullReferenceException
- or IndexOutOfRangeException
- or KeyNotFoundException;
- }
-
- private async ValueTask
SaveChangesCoreAsync(CancellationToken cancellationToken)
- {
- using var l = await this._lock.LockAsync();
-
- // when we have a change publisher attached, we want to get the changed entries before accepting them.
- // Otherwise, we can accept them.
- var acceptChanges = true;
-
- object? sender = null;
- SavedChangesEventArgs? args = null;
- if (this._changeListener is { })
- {
- this.Context.SavedChanges += OnSavedChanges;
- acceptChanges = false;
- }
-
- try
- {
- await this.Context.SaveChangesAsync(acceptChanges, cancellationToken).ConfigureAwait(false);
-
- if (args is not null)
- {
- await this.OnSavedChangesAsync(sender, args).ConfigureAwait(false);
- }
- }
- finally
- {
- this.Context.SavedChanges -= OnSavedChanges;
- }
-
- return true;
-
- void OnSavedChanges(object? s, SavedChangesEventArgs e)
- {
- sender = s;
- args = e;
- }
- }
-
///
public IDisposable SuspendChangeNotifications()
{
@@ -323,6 +260,69 @@ internal class EntityFrameworkContextBase : IContext
this.Context.Dispose();
}
+ ///
+ /// Determines whether the exception is a transient conflict caused by a concurrent entity mutation
+ /// racing this save, and is therefore worth retrying.
+ ///
+ /// The exception thrown by the save.
+ /// true if the save should be retried.
+ private static bool IsTransientConcurrencyConflict(Exception exception)
+ {
+ // A concurrent entity mutation racing this save corrupts the change tracker mid-enumeration.
+ // Depending on exactly where change detection was, it surfaces as one of several types - a
+ // modified collection (InvalidOperationException), a transiently-null internal key
+ // (ArgumentNullException/NullReferenceException), or an out-of-range index. All are transient:
+ // the racing mutation is a single quick operation, so a bounded retry lands on a stable moment.
+ // A genuinely persistent error of the same type is not masked - it rethrows once the retries
+ // are exhausted. The deterministic serialization (per-player persistence lock) is the primary
+ // guard; this retry only needs to absorb the rare, bursty sources that lock isn't held for.
+ return exception is DbUpdateConcurrencyException
+ or InvalidOperationException
+ or ArgumentNullException
+ or NullReferenceException
+ or IndexOutOfRangeException
+ or KeyNotFoundException;
+ }
+
+ private async ValueTask SaveChangesCoreAsync(CancellationToken cancellationToken)
+ {
+ using var l = await this._lock.LockAsync();
+
+ // when we have a change publisher attached, we want to get the changed entries before accepting them.
+ // Otherwise, we can accept them.
+ var acceptChanges = true;
+
+ object? sender = null;
+ SavedChangesEventArgs? args = null;
+ if (this._changeListener is { })
+ {
+ this.Context.SavedChanges += OnSavedChanges;
+ acceptChanges = false;
+ }
+
+ try
+ {
+ await this.Context.SaveChangesAsync(acceptChanges, cancellationToken).ConfigureAwait(false);
+
+ if (args is not null)
+ {
+ await this.OnSavedChangesAsync(sender, args).ConfigureAwait(false);
+ }
+ }
+ finally
+ {
+ this.Context.SavedChanges -= OnSavedChanges;
+ }
+
+ return true;
+
+ void OnSavedChanges(object? s, SavedChangesEventArgs e)
+ {
+ sender = s;
+ args = e;
+ }
+ }
+
private bool DetachInternal(object item)
{
var entry = this.Context.Entry(item);
diff --git a/src/Persistence/EntityFramework/Migrations/20260730194321_AddCastleSiege.cs b/src/Persistence/EntityFramework/Migrations/20260730194321_AddCastleSiege.cs
index d1bceb0..d40faa7 100644
--- a/src/Persistence/EntityFramework/Migrations/20260730194321_AddCastleSiege.cs
+++ b/src/Persistence/EntityFramework/Migrations/20260730194321_AddCastleSiege.cs
@@ -34,7 +34,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
TaxStore = table.Column(type: "smallint", nullable: false),
TaxHunt = table.Column(type: "integer", nullable: false),
IsHuntZoneEnabled = table.Column(type: "boolean", nullable: false),
- TributeMoney = table.Column(type: "bigint", nullable: false)
+ TributeMoney = table.Column(type: "bigint", nullable: false),
},
constraints: table =>
{
@@ -53,7 +53,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
DefenseLevel = table.Column(type: "smallint", nullable: false),
RegenLevel = table.Column(type: "smallint", nullable: false),
LifeLevel = table.Column(type: "smallint", nullable: false),
- CurrentHp = table.Column(type: "integer", nullable: false)
+ CurrentHp = table.Column(type: "integer", nullable: false),
},
constraints: table =>
{
@@ -87,7 +87,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
GuildScoreCastleSiege = table.Column(type: "integer", nullable: false),
GuildScoreCastleSiegeMembers = table.Column(type: "integer", nullable: false),
GateBuyPrice = table.Column(type: "integer", nullable: false),
- StatueBuyPrice = table.Column(type: "integer", nullable: false)
+ StatueBuyPrice = table.Column(type: "integer", nullable: false),
},
constraints: table =>
{
@@ -125,7 +125,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
DefaultSide = table.Column(type: "smallint", nullable: false),
SpawnX = table.Column(type: "smallint", nullable: false),
SpawnY = table.Column(type: "smallint", nullable: false),
- Direction = table.Column(type: "integer", nullable: false)
+ Direction = table.Column(type: "integer", nullable: false),
},
constraints: table =>
{
@@ -155,7 +155,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
State = table.Column(type: "smallint", nullable: false),
DayOfWeek = table.Column(type: "integer", nullable: false),
Hour = table.Column(type: "smallint", nullable: false),
- Minute = table.Column(type: "smallint", nullable: false)
+ Minute = table.Column(type: "smallint", nullable: false),
},
constraints: table =>
{
@@ -183,7 +183,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
Level = table.Column(type: "smallint", nullable: false),
RequiredJewelOfGuardianCount = table.Column(type: "integer", nullable: false),
RequiredZen = table.Column(type: "integer", nullable: false),
- Value = table.Column(type: "integer", nullable: false)
+ Value = table.Column(type: "integer", nullable: false),
},
constraints: table =>
{
@@ -236,7 +236,7 @@ namespace MUnique.OpenMU.Persistence.EntityFramework.Migrations
X1 = table.Column(type: "smallint", nullable: false),
Y1 = table.Column(type: "smallint", nullable: false),
X2 = table.Column(type: "smallint", nullable: false),
- Y2 = table.Column(type: "smallint", nullable: false)
+ Y2 = table.Column(type: "smallint", nullable: false),
},
constraints: table =>
{
diff --git a/src/Web/AdminPanel/Components/Layout/CreationPanel.razor b/src/Web/AdminPanel/Components/Layout/CreationPanel.razor
index 855e43d..e6dad5d 100644
--- a/src/Web/AdminPanel/Components/Layout/CreationPanel.razor
+++ b/src/Web/AdminPanel/Components/Layout/CreationPanel.razor
@@ -8,7 +8,7 @@
@implements IDisposable
@inject CreationPanelService Panel
-@inject Blazored.Toast.Services.IToastService ToastService
+@inject IToastService ToastService
@if (this.Panel.Current is { } session)
{
diff --git a/src/Web/AdminPanel/Components/Layout/MainLayout.razor b/src/Web/AdminPanel/Components/Layout/MainLayout.razor
index 429c724..ff9f4f4 100644
--- a/src/Web/AdminPanel/Components/Layout/MainLayout.razor
+++ b/src/Web/AdminPanel/Components/Layout/MainLayout.razor
@@ -39,7 +39,7 @@