acdream/src/AcDream.App/UI/RetailItemConfirmationController.cs
Erik 66bdae7a83 feat(ui): port retail dialog factory lifecycle
Replace the single mutable confirmation service with retail's property-backed DialogFactory model: fresh DAT roots, context ids, queue groups, priority preemption, callback/close-notice ordering, and context cancellation. Route /die, server confirmation aborts, and guarded item use through focused semantic owners.

Co-Authored-By: Codex <codex@openai.com>
2026-07-13 16:30:05 +02:00

65 lines
2.5 KiB
C#

using AcDream.App.UI.Layout;
using AcDream.Core.Items;
namespace AcDream.App.UI;
/// <summary>
/// Retained UI owner for the item-use confirmations emitted by
/// <see cref="ItemInteractionController"/>. Message/data construction mirrors
/// <c>ClientUISystem::UsageConfirmation_* @ 0x00566420..0x005669EA</c> and
/// completion mirrors <c>ClientUISystem::UsageCallback @ 0x00565B20</c>.
/// </summary>
public sealed class RetailItemConfirmationController : IDisposable
{
internal const string PlayerKillerMessage =
"Using this altar will make you a player killer, able to attack or be attacked by other player killers. Are you sure you want to do this?";
internal const string NonPlayerKillerMessage =
"Using this altar will make you a non-player killer, unable to attack or be attacked by other player killers. Are you sure you want to do this?";
internal const string VolatileRareMessage =
"Are you sure you want to use this rare item?";
private readonly RetailDialogFactory _dialogs;
private readonly ItemInteractionController _items;
private bool _disposed;
public RetailItemConfirmationController(
RetailDialogFactory dialogs,
ItemInteractionController items)
{
_dialogs = dialogs ?? throw new ArgumentNullException(nameof(dialogs));
_items = items ?? throw new ArgumentNullException(nameof(items));
_items.PolicyActionRequested += OnPolicyActionRequested;
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
_items.PolicyActionRequested -= OnPolicyActionRequested;
}
private void OnPolicyActionRequested(ItemPolicyAction action)
{
string? message = action.Kind switch
{
ItemPolicyActionKind.ConfirmPlayerKillerSwitch => PlayerKillerMessage,
ItemPolicyActionKind.ConfirmNonPlayerKillerSwitch => NonPlayerKillerMessage,
ItemPolicyActionKind.ConfirmVolatileRare => VolatileRareMessage,
_ => null,
};
if (message is null)
return;
RetailDialogData data = RetailDialogData.Confirmation(message)
.Set(RetailDialogProperty.UsageObjectId, action.ObjectId);
_dialogs.MakeDialog(data, OnUsageDialogDone);
}
private void OnUsageDialogDone(RetailDialogData data)
{
if (!data.GetBoolean(RetailDialogProperty.ConfirmationResult))
return;
uint objectId = data.GetUInt32(RetailDialogProperty.UsageObjectId);
_items.ExecuteConfirmedUse(objectId);
}
}