From 2ed125d520d6638d2cff8e80495d790e8144525d Mon Sep 17 00:00:00 2001 From: Dean Sheather Date: Tue, 9 Apr 2024 18:20:05 +1000 Subject: [PATCH] feat: allow tab input channel to be set to ExtraChat Adds ExtraChat Linkshell channels to tab input channel selector. These are only by index, not by channel name due to limitations in the ExtraChat IPC API. Adds ExtraChat Linkshell channels to the channel selector in the chat log window. As these aren't real channels in-game, these are handled by just sending the corresponding `/eclX` command which causes ExtraChat to set a channel override. --- ChatTwo/Code/ChatType.cs | 10 ++++ ChatTwo/Code/ChatTypeExt.cs | 8 +++ ChatTwo/Code/InputChannel.cs | 10 ++++ ChatTwo/Code/InputChannelExt.cs | 36 +++++++++++++ ChatTwo/GameFunctions/Chat.cs | 7 ++- ChatTwo/PayloadHandler.cs | 2 +- ChatTwo/Resources/Language.Designer.cs | 72 ++++++++++++++++++++++++++ ChatTwo/Resources/Language.resx | 24 +++++++++ ChatTwo/Ui/ChatLogWindow.cs | 51 +++++++++++++++--- 9 files changed, 210 insertions(+), 10 deletions(-) diff --git a/ChatTwo/Code/ChatType.cs b/ChatTwo/Code/ChatType.cs index 2daa3f8..89e0e4b 100755 --- a/ChatTwo/Code/ChatType.cs +++ b/ChatTwo/Code/ChatType.cs @@ -84,4 +84,14 @@ internal enum ChatType : ushort { CrossLinkshell6 = 105, CrossLinkshell7 = 106, CrossLinkshell8 = 107, + + // Custom types: + ExtraChatLinkshell1 = 1001, + ExtraChatLinkshell2 = 1002, + ExtraChatLinkshell3 = 1003, + ExtraChatLinkshell4 = 1004, + ExtraChatLinkshell5 = 1005, + ExtraChatLinkshell6 = 1006, + ExtraChatLinkshell7 = 1007, + ExtraChatLinkshell8 = 1008, } diff --git a/ChatTwo/Code/ChatTypeExt.cs b/ChatTwo/Code/ChatTypeExt.cs index ecec90f..8b94d50 100755 --- a/ChatTwo/Code/ChatTypeExt.cs +++ b/ChatTwo/Code/ChatTypeExt.cs @@ -162,6 +162,14 @@ internal static class ChatTypeExt { ChatType.CrossLinkshell6 => Language.ChatType_CrossLinkshell6, ChatType.CrossLinkshell7 => Language.ChatType_CrossLinkshell7, ChatType.CrossLinkshell8 => Language.ChatType_CrossLinkshell8, + ChatType.ExtraChatLinkshell1 => Language.ChatType_ExtraChatLinkshell1, + ChatType.ExtraChatLinkshell2 => Language.ChatType_ExtraChatLinkshell2, + ChatType.ExtraChatLinkshell3 => Language.ChatType_ExtraChatLinkshell3, + ChatType.ExtraChatLinkshell4 => Language.ChatType_ExtraChatLinkshell4, + ChatType.ExtraChatLinkshell5 => Language.ChatType_ExtraChatLinkshell5, + ChatType.ExtraChatLinkshell6 => Language.ChatType_ExtraChatLinkshell6, + ChatType.ExtraChatLinkshell7 => Language.ChatType_ExtraChatLinkshell7, + ChatType.ExtraChatLinkshell8 => Language.ChatType_ExtraChatLinkshell8, _ => type.ToString(), }; } diff --git a/ChatTwo/Code/InputChannel.cs b/ChatTwo/Code/InputChannel.cs index 6929285..31b3f2b 100755 --- a/ChatTwo/Code/InputChannel.cs +++ b/ChatTwo/Code/InputChannel.cs @@ -29,4 +29,14 @@ internal enum InputChannel : uint { Linkshell6 = 24, Linkshell7 = 25, Linkshell8 = 26, + + // Custom channels: + ExtraChatLinkshell1 = 1001, + ExtraChatLinkshell2 = 1002, + ExtraChatLinkshell3 = 1003, + ExtraChatLinkshell4 = 1004, + ExtraChatLinkshell5 = 1005, + ExtraChatLinkshell6 = 1006, + ExtraChatLinkshell7 = 1007, + ExtraChatLinkshell8 = 1008, } diff --git a/ChatTwo/Code/InputChannelExt.cs b/ChatTwo/Code/InputChannelExt.cs index 215e2bf..906e878 100755 --- a/ChatTwo/Code/InputChannelExt.cs +++ b/ChatTwo/Code/InputChannelExt.cs @@ -30,6 +30,14 @@ internal static class InputChannelExt { InputChannel.Linkshell6 => ChatType.Linkshell6, InputChannel.Linkshell7 => ChatType.Linkshell7, InputChannel.Linkshell8 => ChatType.Linkshell8, + InputChannel.ExtraChatLinkshell1 => ChatType.ExtraChatLinkshell1, + InputChannel.ExtraChatLinkshell2 => ChatType.ExtraChatLinkshell2, + InputChannel.ExtraChatLinkshell3 => ChatType.ExtraChatLinkshell3, + InputChannel.ExtraChatLinkshell4 => ChatType.ExtraChatLinkshell4, + InputChannel.ExtraChatLinkshell5 => ChatType.ExtraChatLinkshell5, + InputChannel.ExtraChatLinkshell6 => ChatType.ExtraChatLinkshell6, + InputChannel.ExtraChatLinkshell7 => ChatType.ExtraChatLinkshell7, + InputChannel.ExtraChatLinkshell8 => ChatType.ExtraChatLinkshell8, _ => throw new ArgumentOutOfRangeException(nameof(input), input, null), }; @@ -50,6 +58,14 @@ internal static class InputChannelExt { InputChannel.CrossLinkshell6 => 5, InputChannel.CrossLinkshell7 => 6, InputChannel.CrossLinkshell8 => 7, + InputChannel.ExtraChatLinkshell1 => 0, + InputChannel.ExtraChatLinkshell2 => 1, + InputChannel.ExtraChatLinkshell3 => 2, + InputChannel.ExtraChatLinkshell4 => 3, + InputChannel.ExtraChatLinkshell5 => 4, + InputChannel.ExtraChatLinkshell6 => 5, + InputChannel.ExtraChatLinkshell7 => 6, + InputChannel.ExtraChatLinkshell8 => 7, _ => uint.MaxValue, }; @@ -79,6 +95,14 @@ internal static class InputChannelExt { InputChannel.Linkshell6 => "/linkshell6", InputChannel.Linkshell7 => "/linkshell7", InputChannel.Linkshell8 => "/linkshell8", + InputChannel.ExtraChatLinkshell1 => "/ecl1", + InputChannel.ExtraChatLinkshell2 => "/ecl2", + InputChannel.ExtraChatLinkshell3 => "/ecl3", + InputChannel.ExtraChatLinkshell4 => "/ecl4", + InputChannel.ExtraChatLinkshell5 => "/ecl5", + InputChannel.ExtraChatLinkshell6 => "/ecl6", + InputChannel.ExtraChatLinkshell7 => "/ecl7", + InputChannel.ExtraChatLinkshell8 => "/ecl8", _ => "", }; @@ -150,4 +174,16 @@ internal static class InputChannelExt { InputChannel.CrossLinkshell8 => true, _ => false, }; + + internal static bool IsExtraChatLinkshell(this InputChannel channel) => channel switch { + InputChannel.ExtraChatLinkshell1 => true, + InputChannel.ExtraChatLinkshell2 => true, + InputChannel.ExtraChatLinkshell3 => true, + InputChannel.ExtraChatLinkshell4 => true, + InputChannel.ExtraChatLinkshell5 => true, + InputChannel.ExtraChatLinkshell6 => true, + InputChannel.ExtraChatLinkshell7 => true, + InputChannel.ExtraChatLinkshell8 => true, + _ => false, + }; } diff --git a/ChatTwo/GameFunctions/Chat.cs b/ChatTwo/GameFunctions/Chat.cs index 33ff0c9..141a11b 100755 --- a/ChatTwo/GameFunctions/Chat.cs +++ b/ChatTwo/GameFunctions/Chat.cs @@ -611,7 +611,12 @@ internal sealed unsafe class Chat : IDisposable { } internal void SetChannel(InputChannel channel, string? tellTarget = null) { - if (ChangeChatChannel == null) + // ExtraChat linkshells aren't supported in game so we never want to + // call the ChangeChatChannel function with them. + // + // Callers should call ChatLogWindow.SetChannel() which handles + // ExtraChat channels + if (ChangeChatChannel == null || channel.IsExtraChatLinkshell()) return; var target = Utf8String.FromString(tellTarget ?? ""); diff --git a/ChatTwo/PayloadHandler.cs b/ChatTwo/PayloadHandler.cs index a971615..5170d5a 100755 --- a/ChatTwo/PayloadHandler.cs +++ b/ChatTwo/PayloadHandler.cs @@ -592,7 +592,7 @@ public sealed class PayloadHandler { var inputChannel = chunk.Message?.Code.Type.ToInputChannel(); if (inputChannel != null && ImGui.Selectable(Language.Context_ReplyInSelectedChatMode)) { - LogWindow.Plugin.Functions.Chat.SetChannel(inputChannel.Value); + LogWindow.SetChannel(inputChannel.Value); LogWindow.Activate = true; } diff --git a/ChatTwo/Resources/Language.Designer.cs b/ChatTwo/Resources/Language.Designer.cs index 2412b26..bce47a3 100755 --- a/ChatTwo/Resources/Language.Designer.cs +++ b/ChatTwo/Resources/Language.Designer.cs @@ -419,6 +419,78 @@ namespace ChatTwo.Resources { } } + /// + /// Looks up a localized string similar to ExtraChat Linkshell [1]. + /// + internal static string ChatType_ExtraChatLinkshell1 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell1", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [2]. + /// + internal static string ChatType_ExtraChatLinkshell2 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell2", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [3]. + /// + internal static string ChatType_ExtraChatLinkshell3 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell3", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [4]. + /// + internal static string ChatType_ExtraChatLinkshell4 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell4", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [5]. + /// + internal static string ChatType_ExtraChatLinkshell5 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell5", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [6]. + /// + internal static string ChatType_ExtraChatLinkshell6 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell6", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [7]. + /// + internal static string ChatType_ExtraChatLinkshell7 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell7", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to ExtraChat Linkshell [8]. + /// + internal static string ChatType_ExtraChatLinkshell8 { + get { + return ResourceManager.GetString("ChatType_ExtraChatLinkshell8", resourceCulture); + } + } + /// /// Looks up a localized string similar to Free Company. /// diff --git a/ChatTwo/Resources/Language.resx b/ChatTwo/Resources/Language.resx index 4af8f8a..8609d85 100644 --- a/ChatTwo/Resources/Language.resx +++ b/ChatTwo/Resources/Language.resx @@ -871,4 +871,28 @@ Use this option if you experience cut-off tooltips. + + ExtraChat Linkshell [1] + + + ExtraChat Linkshell [2] + + + ExtraChat Linkshell [3] + + + ExtraChat Linkshell [4] + + + ExtraChat Linkshell [5] + + + ExtraChat Linkshell [6] + + + ExtraChat Linkshell [7] + + + ExtraChat Linkshell [8] + diff --git a/ChatTwo/Ui/ChatLogWindow.cs b/ChatTwo/Ui/ChatLogWindow.cs index c5f73f6..b665d01 100644 --- a/ChatTwo/Ui/ChatLogWindow.cs +++ b/ChatTwo/Ui/ChatLogWindow.cs @@ -136,7 +136,7 @@ public sealed class ChatLogWindow : Window, IUiComponent { var prevTemp = _tempChannel; if (info.Permanent) { - Plugin.Functions.Chat.SetChannel(info.Channel.Value); + SetChannel(info.Channel.Value); } else { _tempChannel = info.Channel.Value; } @@ -481,7 +481,17 @@ public sealed class ChatLogWindow : Window, IUiComponent { ImGui.TextUnformatted(_tempChannel.Value.ToChatType().Name()); } } else if (activeTab is { Channel: { } channel }) { - ImGui.TextUnformatted(channel.ToChatType().Name()); + if (channel.IsExtraChatLinkshell()) { + // We cannot lookup ExtraChat channel names from index over + // IPC so we just don't show the name if it's the tabs + // channel. + // + // We don't call channel.ToChatType().Name() as it has the + // long name as used in the settings window. + ImGui.TextUnformatted($"ECLS [{channel.LinkshellIndex() + 1}]"); + } else { + ImGui.TextUnformatted(channel.ToChatType().Name()); + } } else if (Plugin.ExtraChat.ChannelOverride is var (overrideName, _)) { ImGui.TextUnformatted(overrideName); } else { @@ -510,7 +520,7 @@ public sealed class ChatLogWindow : Window, IUiComponent { var name = Plugin.DataManager.GetExcelSheet()! .FirstOrDefault(row => row.LogKind == (byte) channel.ToChatType()) ?.Name - ?.RawString ?? channel.ToString(); + ?.RawString ?? channel.ToChatType().Name(); if (channel.IsLinkshell()) { var lsName = Plugin.Functions.Chat.GetLinkshellName(channel.LinkshellIndex()); @@ -530,9 +540,18 @@ public sealed class ChatLogWindow : Window, IUiComponent { name += $": {lsName}"; } + if (channel.IsExtraChatLinkshell() && Plugin.ExtraChat.ChannelNames.Count == 0) { + // Sadly the ExtraChat IPC doesn't provide a method to + // lookup what channel numbers are assigned, or what the + // channel names are. + // + // Show all ExtraChat options if the user is in at least + // one channel. + continue; + } + if (ImGui.Selectable(name)) { - Plugin.Functions.Chat.SetChannel(channel); - _tellTarget = null; + SetChannel(channel); } } @@ -594,7 +613,7 @@ public sealed class ChatLogWindow : Window, IUiComponent { if (Plugin.Functions.Chat.UsesTellTempChannel) { Plugin.Functions.Chat.UsesTellTempChannel = false; - Plugin.Functions.Chat.SetChannel(Plugin.Functions.Chat.PreviousChannel ?? InputChannel.Say); + SetChannel(Plugin.Functions.Chat.PreviousChannel); } } @@ -606,7 +625,7 @@ public sealed class ChatLogWindow : Window, IUiComponent { if (Plugin.Functions.Chat.UsesTellTempChannel) { Plugin.Functions.Chat.UsesTellTempChannel = false; - Plugin.Functions.Chat.SetChannel(Plugin.Functions.Chat.PreviousChannel ?? InputChannel.Say); + SetChannel(Plugin.Functions.Chat.PreviousChannel); } } } @@ -624,7 +643,7 @@ public sealed class ChatLogWindow : Window, IUiComponent { if (Plugin.Functions.Chat.UsesTellTempChannel) { Plugin.Functions.Chat.UsesTellTempChannel = false; - Plugin.Functions.Chat.SetChannel(Plugin.Functions.Chat.PreviousChannel ?? InputChannel.Say); + SetChannel(Plugin.Functions.Chat.PreviousChannel); } } @@ -661,6 +680,22 @@ public sealed class ChatLogWindow : Window, IUiComponent { } } + internal void SetChannel(InputChannel? channel) + { + channel ??= InputChannel.Say; + + _tellTarget = null; + if (channel.Value.IsExtraChatLinkshell()) { + // Instead of calling SetChannel(), we ask the ExtraChat plugin to + // set a channel override by just calling the command directly. + var bytes = Encoding.UTF8.GetBytes(channel.Value.Prefix()); + Plugin.Common.Functions.Chat.SendMessageUnsafe(bytes); + return; + } + + Plugin.Functions.Chat.SetChannel(channel.Value); + } + private void SendChatBox(Tab? activeTab) { if (!string.IsNullOrWhiteSpace(Chat)) { var trimmed = Chat.Trim();