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();