From 482bc6684c95ab3bb29c9cd9bc82c7121634ec97 Mon Sep 17 00:00:00 2001 From: Ethan Moffat Date: Tue, 13 Sep 2022 23:46:23 -0700 Subject: [PATCH] Implement MESSAGE_ACCEPT handler. Allows for more player commands to work on BU Note that the dialog text is currently hacked into multiple lines based on observations from BU using spaces to pad messages into multiple lines --- .../Notifiers/IUserInterfaceNotifier.cs | 16 +++++++ .../Message/MessageAcceptHandler.cs | 42 +++++++++++++++++++ .../Dialogs/Actions/InGameDialogActions.cs | 36 ++++++++++++++++ .../Dialogs/ActiveDialogRepository.cs | 8 ++++ .../Factories/ScrollingListDialogFactory.cs | 30 +++++++++++++ EndlessClient/HUD/ServerMessageActions.cs | 23 ++++++++++ 6 files changed, 155 insertions(+) create mode 100644 EOLib/Domain/Notifiers/IUserInterfaceNotifier.cs create mode 100644 EOLib/PacketHandlers/Message/MessageAcceptHandler.cs create mode 100644 EndlessClient/Dialogs/Factories/ScrollingListDialogFactory.cs create mode 100644 EndlessClient/HUD/ServerMessageActions.cs diff --git a/EOLib/Domain/Notifiers/IUserInterfaceNotifier.cs b/EOLib/Domain/Notifiers/IUserInterfaceNotifier.cs new file mode 100644 index 000000000..e12bc6e8d --- /dev/null +++ b/EOLib/Domain/Notifiers/IUserInterfaceNotifier.cs @@ -0,0 +1,16 @@ +using AutomaticTypeMapper; +using System.Collections.Generic; + +namespace EOLib.Domain.Notifiers +{ + public interface IUserInterfaceNotifier + { + void NotifyMessageDialog(string title, IReadOnlyList messages); + } + + [AutoMappedType] + public class NoOpUserInterfaceNotifier : IUserInterfaceNotifier + { + public void NotifyMessageDialog(string title, IReadOnlyList messages) { } + } +} diff --git a/EOLib/PacketHandlers/Message/MessageAcceptHandler.cs b/EOLib/PacketHandlers/Message/MessageAcceptHandler.cs new file mode 100644 index 000000000..c3f23458e --- /dev/null +++ b/EOLib/PacketHandlers/Message/MessageAcceptHandler.cs @@ -0,0 +1,42 @@ +using AutomaticTypeMapper; +using EOLib.Domain.Login; +using EOLib.Domain.Notifiers; +using EOLib.Net; +using EOLib.Net.Handlers; +using System.Collections.Generic; + +namespace EOLib.PacketHandlers.Message +{ + /// + /// Shows a message dialog (ScrollingListDialogSize.Large, ScrollingListDialog.ListItemStyle.Small) + /// + [AutoMappedType] + public class MessageAcceptHandler : InGameOnlyPacketHandler + { + private readonly IEnumerable _userInterfaceNotifiers; + + public override PacketFamily Family => PacketFamily.Message; + + public override PacketAction Action => PacketAction.Accept; + + public MessageAcceptHandler(IPlayerInfoProvider playerInfoProvider, + IEnumerable userInterfaceNotifiers) + : base(playerInfoProvider) + { + _userInterfaceNotifiers = userInterfaceNotifiers; + } + + public override bool HandlePacket(IPacket packet) + { + var title = packet.ReadBreakString(); + var messages = new List(); + while (packet.ReadPosition < packet.Length) + messages.Add(packet.ReadBreakString()); + + foreach (var notifier in _userInterfaceNotifiers) + notifier.NotifyMessageDialog(title, messages); + + return true; + } + } +} diff --git a/EndlessClient/Dialogs/Actions/InGameDialogActions.cs b/EndlessClient/Dialogs/Actions/InGameDialogActions.cs index 083c46e00..37521c394 100644 --- a/EndlessClient/Dialogs/Actions/InGameDialogActions.cs +++ b/EndlessClient/Dialogs/Actions/InGameDialogActions.cs @@ -7,6 +7,8 @@ using EOLib.Domain.Interact.Skill; using Optional; using System; +using System.Collections.Generic; +using System.Linq; namespace EndlessClient.Dialogs.Actions { @@ -26,6 +28,7 @@ public class InGameDialogActions : IInGameDialogActions private readonly IBankAccountDialogFactory _bankAccountDialogFactory; private readonly ISkillmasterDialogFactory _skillmasterDialogFactory; private readonly IBardDialogFactory _bardDialogFactory; + private readonly IScrollingListDialogFactory _scrollingListDialogFactory; private readonly ISfxPlayer _sfxPlayer; private readonly IShopDialogFactory _shopDialogFactory; private readonly IQuestDialogFactory _questDialogFactory; @@ -45,6 +48,7 @@ public InGameDialogActions(IFriendIgnoreListDialogFactory friendIgnoreListDialog IBankAccountDialogFactory bankAccountDialogFactory, ISkillmasterDialogFactory skillmasterDialogFactory, IBardDialogFactory bardDialogFactory, + IScrollingListDialogFactory scrollingListDialogFactory, ISfxPlayer sfxPlayer) { _friendIgnoreListDialogFactory = friendIgnoreListDialogFactory; @@ -60,6 +64,7 @@ public InGameDialogActions(IFriendIgnoreListDialogFactory friendIgnoreListDialog _bankAccountDialogFactory = bankAccountDialogFactory; _skillmasterDialogFactory = skillmasterDialogFactory; _bardDialogFactory = bardDialogFactory; + _scrollingListDialogFactory = scrollingListDialogFactory; _sfxPlayer = sfxPlayer; _shopDialogFactory = shopDialogFactory; _questDialogFactory = questDialogFactory; @@ -247,6 +252,35 @@ public void ShowBardDialog() }); } + public void ShowMessageDialog(string title, IReadOnlyList messages) + { + _activeDialogRepository.MessageDialog.MatchNone(() => + { + var dlg = _scrollingListDialogFactory.Create(ScrollingListDialogSize.Large); + dlg.DialogClosed += (_, _) => _activeDialogRepository.MessageDialog = Option.None(); + + dlg.ListItemType = ListDialogItem.ListItemStyle.Small; + dlg.Buttons = ScrollingListDialogButtons.Cancel; + dlg.Title = title; + + var _75spaces = new string(Enumerable.Repeat(' ', 75).ToArray()); + var items = messages + // BU hack - assume that 75 spaces or more indicates an extra line break + .Select(x => x.Replace(_75spaces, " \n")) + // BU hack - assume that 3 spaces or more indicates extra padding and should split the message into multiple lines + .SelectMany(x => x.Split(" ", StringSplitOptions.RemoveEmptyEntries)) + .Select(x => new ListDialogItem(dlg, ListDialogItem.ListItemStyle.Small) { PrimaryText = x == "\n" ? string.Empty : x.Trim() }).ToList(); + + dlg.SetItemList(items); + + _activeDialogRepository.MessageDialog = Option.Some(dlg); + + UseDefaultDialogSounds(dlg); + + dlg.Show(); + }); + } + private void UseDefaultDialogSounds(ScrollingListDialog dialog) { UseDefaultDialogSounds((BaseEODialog)dialog); @@ -298,5 +332,7 @@ public interface IInGameDialogActions void ShowSkillmasterDialog(); void ShowBardDialog(); + + void ShowMessageDialog(string title, IReadOnlyList messages); } } diff --git a/EndlessClient/Dialogs/ActiveDialogRepository.cs b/EndlessClient/Dialogs/ActiveDialogRepository.cs index 7b2405386..cca28ff36 100644 --- a/EndlessClient/Dialogs/ActiveDialogRepository.cs +++ b/EndlessClient/Dialogs/ActiveDialogRepository.cs @@ -31,6 +31,8 @@ public interface IActiveDialogProvider : IDisposable Option BardDialog { get; } + Option MessageDialog { get; } + IReadOnlyList> ActiveDialogs { get; } } @@ -58,6 +60,8 @@ public interface IActiveDialogRepository : IDisposable Option BardDialog { get; set; } + Option MessageDialog { get; set; } + IReadOnlyList> ActiveDialogs { get; } } @@ -86,6 +90,8 @@ public class ActiveDialogRepository : IActiveDialogRepository, IActiveDialogProv public Option BardDialog { get; set; } + public Option MessageDialog { get; set; } + IReadOnlyList> ActiveDialogs { get @@ -103,6 +109,7 @@ IReadOnlyList> ActiveDialogs BankAccountDialog.Map(d => (IXNADialog)d), SkillmasterDialog.Map(d => (IXNADialog)d), BardDialog.Map(d => (IXNADialog)d), + MessageDialog.Map(d => (IXNADialog)d), }.ToList(); } } @@ -127,6 +134,7 @@ public void Dispose() BankAccountDialog = Option.None(); SkillmasterDialog = Option.None(); BardDialog = Option.None(); + MessageDialog = Option.None(); } } } diff --git a/EndlessClient/Dialogs/Factories/ScrollingListDialogFactory.cs b/EndlessClient/Dialogs/Factories/ScrollingListDialogFactory.cs new file mode 100644 index 000000000..93d7ec493 --- /dev/null +++ b/EndlessClient/Dialogs/Factories/ScrollingListDialogFactory.cs @@ -0,0 +1,30 @@ +using AutomaticTypeMapper; +using EndlessClient.Dialogs.Services; +using EOLib.Graphics; + +namespace EndlessClient.Dialogs.Factories +{ + [AutoMappedType] + public class ScrollingListDialogFactory : IScrollingListDialogFactory + { + private readonly INativeGraphicsManager _nativeGraphicsManager; + private readonly IEODialogButtonService _dialogButtonService; + + public ScrollingListDialogFactory(INativeGraphicsManager nativeGraphicsManager, + IEODialogButtonService dialogButtonService) + { + _nativeGraphicsManager = nativeGraphicsManager; + _dialogButtonService = dialogButtonService; + } + + public ScrollingListDialog Create(ScrollingListDialogSize size) + { + return new ScrollingListDialog(_nativeGraphicsManager, _dialogButtonService, size); + } + } + + public interface IScrollingListDialogFactory + { + ScrollingListDialog Create(ScrollingListDialogSize size); + } +} diff --git a/EndlessClient/HUD/ServerMessageActions.cs b/EndlessClient/HUD/ServerMessageActions.cs new file mode 100644 index 000000000..ff63e3f95 --- /dev/null +++ b/EndlessClient/HUD/ServerMessageActions.cs @@ -0,0 +1,23 @@ +using AutomaticTypeMapper; +using EndlessClient.Dialogs.Actions; +using EOLib.Domain.Notifiers; +using System.Collections.Generic; + +namespace EndlessClient.HUD +{ + [AutoMappedType] + public class ServerMessageActions : IUserInterfaceNotifier + { + private readonly IInGameDialogActions _inGameDialogActions; + + public ServerMessageActions(IInGameDialogActions inGameDialogActions) + { + _inGameDialogActions = inGameDialogActions; + } + + public void NotifyMessageDialog(string title, IReadOnlyList messages) + { + _inGameDialogActions.ShowMessageDialog(title, messages); + } + } +}