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 b286f76..0722a03 100755 --- a/ChatTwo/PayloadHandler.cs +++ b/ChatTwo/PayloadHandler.cs @@ -623,7 +623,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 cd67b93..01c8b87 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 3e600c4..da1ea88 100644 --- a/ChatTwo/Resources/Language.resx +++ b/ChatTwo/Resources/Language.resx @@ -877,7 +877,30 @@ 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] + Copy content diff --git a/ChatTwo/Ui/ChatLogWindow.cs b/ChatTwo/Ui/ChatLogWindow.cs index 1df0de7..7692a63 100644 --- a/ChatTwo/Ui/ChatLogWindow.cs +++ b/ChatTwo/Ui/ChatLogWindow.cs @@ -151,7 +151,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; } @@ -496,7 +496,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 { @@ -525,7 +535,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()); @@ -545,9 +555,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); } } @@ -609,7 +628,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); } } @@ -621,7 +640,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); } } } @@ -639,7 +658,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); } } @@ -676,6 +695,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();