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.
This commit is contained in:
Dean Sheather
2024-04-09 18:20:05 +10:00
parent fed420901c
commit 2ed125d520
9 changed files with 210 additions and 10 deletions
+10
View File
@@ -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,
}
+8
View File
@@ -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(),
};
}
+10
View File
@@ -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,
}
+36
View File
@@ -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,
};
}
+6 -1
View File
@@ -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 ?? "");
+1 -1
View File
@@ -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;
}
+72
View File
@@ -419,6 +419,78 @@ namespace ChatTwo.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [1].
/// </summary>
internal static string ChatType_ExtraChatLinkshell1 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell1", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [2].
/// </summary>
internal static string ChatType_ExtraChatLinkshell2 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell2", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [3].
/// </summary>
internal static string ChatType_ExtraChatLinkshell3 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell3", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [4].
/// </summary>
internal static string ChatType_ExtraChatLinkshell4 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell4", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [5].
/// </summary>
internal static string ChatType_ExtraChatLinkshell5 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell5", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [6].
/// </summary>
internal static string ChatType_ExtraChatLinkshell6 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell6", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [7].
/// </summary>
internal static string ChatType_ExtraChatLinkshell7 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell7", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to ExtraChat Linkshell [8].
/// </summary>
internal static string ChatType_ExtraChatLinkshell8 {
get {
return ResourceManager.GetString("ChatType_ExtraChatLinkshell8", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Free Company.
/// </summary>
+24
View File
@@ -871,4 +871,28 @@
<data name="Options_TooltipOffset_Desc" xml:space="preserve">
<value>Use this option if you experience cut-off tooltips.</value>
</data>
<data name="ChatType_ExtraChatLinkshell1" xml:space="preserve">
<value>ExtraChat Linkshell [1]</value>
</data>
<data name="ChatType_ExtraChatLinkshell2" xml:space="preserve">
<value>ExtraChat Linkshell [2]</value>
</data>
<data name="ChatType_ExtraChatLinkshell3" xml:space="preserve">
<value>ExtraChat Linkshell [3]</value>
</data>
<data name="ChatType_ExtraChatLinkshell4" xml:space="preserve">
<value>ExtraChat Linkshell [4]</value>
</data>
<data name="ChatType_ExtraChatLinkshell5" xml:space="preserve">
<value>ExtraChat Linkshell [5]</value>
</data>
<data name="ChatType_ExtraChatLinkshell6" xml:space="preserve">
<value>ExtraChat Linkshell [6]</value>
</data>
<data name="ChatType_ExtraChatLinkshell7" xml:space="preserve">
<value>ExtraChat Linkshell [7]</value>
</data>
<data name="ChatType_ExtraChatLinkshell8" xml:space="preserve">
<value>ExtraChat Linkshell [8]</value>
</data>
</root>
+42 -7
View File
@@ -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 }) {
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<LogFilter>()!
.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();