- Check auto translation for commands and execute them instead of sending
- Plugin commands trigger the command helper window now - Fix auto translation with empty text appearing - Switch up all dalamud payload usage to ROSS if possible - Prepare 7.5 changes - Cleanup
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<Project Sdk="Dalamud.NET.Sdk/14.0.1">
|
<Project Sdk="Dalamud.NET.Sdk/14.0.2">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.34.4</Version>
|
<Version>1.34.5</Version>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||||
@@ -53,10 +53,10 @@
|
|||||||
<!-- <Copy SourceFiles="@(Files)" DestinationFolder="$(TargetDir)\Frontend\%(RecursiveDir)" />-->
|
<!-- <Copy SourceFiles="@(Files)" DestinationFolder="$(TargetDir)\Frontend\%(RecursiveDir)" />-->
|
||||||
<!-- </Target>-->
|
<!-- </Target>-->
|
||||||
|
|
||||||
<Target Name="NodeJS Compile" BeforeTargets="BeforeCompile" Condition="'$(Configuration)' == 'Debug'">
|
<!-- <Target Name="NodeJS Compile" BeforeTargets="BeforeCompile" Condition="'$(Configuration)' == 'Debug'">-->
|
||||||
<Exec Command="npm install" WorkingDirectory="Http\Frontend"/>
|
<!-- <Exec Command="npm install" WorkingDirectory="Http\Frontend"/>-->
|
||||||
<Exec Command="npm run build" WorkingDirectory="Http\Frontend"/>
|
<!-- <Exec Command="npm run build" WorkingDirectory="Http\Frontend"/>-->
|
||||||
</Target>
|
<!-- </Target>-->
|
||||||
|
|
||||||
<Target Name="UnzipBuild" AfterTargets="Build">
|
<Target Name="UnzipBuild" AfterTargets="Build">
|
||||||
<Unzip SourceFiles="websiteBuild.zip" DestinationFolder="$(TargetDir)\Frontend"/>
|
<Unzip SourceFiles="websiteBuild.zip" DestinationFolder="$(TargetDir)\Frontend"/>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
namespace ChatTwo.Code;
|
namespace ChatTwo.Code;
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32")]
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum ChatSource : ushort
|
public enum ChatSource : ushort
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,17 +5,10 @@ namespace ChatTwo.Code;
|
|||||||
internal static class ChatSourceExt
|
internal static class ChatSourceExt
|
||||||
{
|
{
|
||||||
internal const ChatSource All =
|
internal const ChatSource All =
|
||||||
ChatSource.Self
|
ChatSource.Self | ChatSource.PartyMember | ChatSource.AllianceMember |
|
||||||
| ChatSource.PartyMember
|
ChatSource.Other | ChatSource.EngagedEnemy | ChatSource.UnengagedEnemy |
|
||||||
| ChatSource.AllianceMember
|
ChatSource.FriendlyNpc | ChatSource.SelfPet | ChatSource.PartyPet |
|
||||||
| ChatSource.Other
|
ChatSource.AlliancePet | ChatSource.OtherPet;
|
||||||
| ChatSource.EngagedEnemy
|
|
||||||
| ChatSource.UnengagedEnemy
|
|
||||||
| ChatSource.FriendlyNpc
|
|
||||||
| ChatSource.SelfPet
|
|
||||||
| ChatSource.PartyPet
|
|
||||||
| ChatSource.AlliancePet
|
|
||||||
| ChatSource.OtherPet;
|
|
||||||
|
|
||||||
internal static string Name(this ChatSource source) => source switch
|
internal static string Name(this ChatSource source) => source switch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
namespace ChatTwo.Code;
|
namespace ChatTwo.Code;
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32")]
|
|
||||||
public enum ChatType : ushort
|
public enum ChatType : ushort
|
||||||
{
|
{
|
||||||
Debug = 1,
|
Debug = 1,
|
||||||
|
|||||||
+11
-16
@@ -6,14 +6,9 @@ namespace ChatTwo.Code;
|
|||||||
|
|
||||||
internal static class ChatTypeExt
|
internal static class ChatTypeExt
|
||||||
{
|
{
|
||||||
internal static IEnumerable<(string, ChatType[])> SortOrder => new[]
|
internal static IEnumerable<(string, ChatType[])> SortOrder =>
|
||||||
{
|
|
||||||
(Language.Options_Tabs_ChannelTypes_Special,
|
|
||||||
[
|
[
|
||||||
ChatType.Debug,
|
(Language.Options_Tabs_ChannelTypes_Special, [ChatType.Debug, ChatType.Urgent, ChatType.Notice]),
|
||||||
ChatType.Urgent,
|
|
||||||
ChatType.Notice
|
|
||||||
]),
|
|
||||||
|
|
||||||
(Language.Options_Tabs_ChannelTypes_Chat,
|
(Language.Options_Tabs_ChannelTypes_Chat,
|
||||||
[
|
[
|
||||||
@@ -48,8 +43,8 @@ internal static class ChatTypeExt
|
|||||||
ChatType.CustomEmote
|
ChatType.CustomEmote
|
||||||
]),
|
]),
|
||||||
|
|
||||||
(Language.Options_Tabs_ChannelTypes_Battle, new[]
|
(Language.Options_Tabs_ChannelTypes_Battle,
|
||||||
{
|
[
|
||||||
ChatType.Damage,
|
ChatType.Damage,
|
||||||
ChatType.Miss,
|
ChatType.Miss,
|
||||||
ChatType.Action,
|
ChatType.Action,
|
||||||
@@ -58,11 +53,11 @@ internal static class ChatTypeExt
|
|||||||
ChatType.GainBuff,
|
ChatType.GainBuff,
|
||||||
ChatType.LoseBuff,
|
ChatType.LoseBuff,
|
||||||
ChatType.GainDebuff,
|
ChatType.GainDebuff,
|
||||||
ChatType.LoseDebuff,
|
ChatType.LoseDebuff
|
||||||
}),
|
]),
|
||||||
|
|
||||||
(Language.Options_Tabs_ChannelTypes_Announcements, new[]
|
(Language.Options_Tabs_ChannelTypes_Announcements,
|
||||||
{
|
[
|
||||||
ChatType.System,
|
ChatType.System,
|
||||||
ChatType.BattleSystem,
|
ChatType.BattleSystem,
|
||||||
ChatType.GatheringSystem,
|
ChatType.GatheringSystem,
|
||||||
@@ -87,11 +82,11 @@ internal static class ChatTypeExt
|
|||||||
ChatType.Orchestrion,
|
ChatType.Orchestrion,
|
||||||
ChatType.MessageBook,
|
ChatType.MessageBook,
|
||||||
ChatType.Alarm,
|
ChatType.Alarm,
|
||||||
ChatType.GlamourNotifications,
|
ChatType.GlamourNotifications
|
||||||
}),
|
])
|
||||||
// Note: ExtraChat linkshells are handled separately in the tab settings
|
// Note: ExtraChat linkshells are handled separately in the tab settings
|
||||||
// UI.
|
// UI.
|
||||||
};
|
];
|
||||||
|
|
||||||
internal static string Name(this ChatType type)
|
internal static string Name(this ChatType type)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Dalamud.Plugin.Services;
|
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
|
||||||
namespace ChatTwo.Code;
|
namespace ChatTwo.Code;
|
||||||
@@ -108,11 +107,10 @@ internal static class InputChannelExt
|
|||||||
InputChannel.ExtraChatLinkshell6 => "/ecl6",
|
InputChannel.ExtraChatLinkshell6 => "/ecl6",
|
||||||
InputChannel.ExtraChatLinkshell7 => "/ecl7",
|
InputChannel.ExtraChatLinkshell7 => "/ecl7",
|
||||||
InputChannel.ExtraChatLinkshell8 => "/ecl8",
|
InputChannel.ExtraChatLinkshell8 => "/ecl8",
|
||||||
InputChannel.Invalid => "/e",
|
|
||||||
_ => "/e",
|
_ => "/e",
|
||||||
};
|
};
|
||||||
|
|
||||||
public static IEnumerable<TextCommand>? TextCommands(this InputChannel channel, IDataManager data)
|
public static IEnumerable<TextCommand>? TextCommands(this InputChannel channel)
|
||||||
{
|
{
|
||||||
var ids = channel switch
|
var ids = channel switch
|
||||||
{
|
{
|
||||||
@@ -147,8 +145,7 @@ internal static class InputChannelExt
|
|||||||
if (ids.Length == 0)
|
if (ids.Length == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var cmds = data.GetExcelSheet<TextCommand>();
|
return ids.Where(id => Sheets.TextCommandSheet.HasRow(id)).Select(id => Sheets.TextCommandSheet.GetRow(id));
|
||||||
return ids.Where(id => cmds.HasRow(id)).Select(id => cmds.GetRow(id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool IsLinkshell(this InputChannel channel) => channel switch
|
internal static bool IsLinkshell(this InputChannel channel) => channel switch
|
||||||
|
|||||||
+3
-8
@@ -4,13 +4,7 @@ namespace ChatTwo;
|
|||||||
|
|
||||||
internal sealed class Commands : IDisposable
|
internal sealed class Commands : IDisposable
|
||||||
{
|
{
|
||||||
private Plugin Plugin { get; }
|
private readonly Dictionary<string, CommandWrapper> Registered = [];
|
||||||
private Dictionary<string, CommandWrapper> Registered { get; } = new();
|
|
||||||
|
|
||||||
internal Commands(Plugin plugin)
|
|
||||||
{
|
|
||||||
Plugin = plugin;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
@@ -47,7 +41,8 @@ internal sealed class Commands : IDisposable
|
|||||||
return Registered[name];
|
return Registered[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Invoke(string command, string arguments) {
|
private void Invoke(string command, string arguments)
|
||||||
|
{
|
||||||
if (!Registered.TryGetValue(command, out var wrapper))
|
if (!Registered.TryGetValue(command, out var wrapper))
|
||||||
{
|
{
|
||||||
Plugin.Log.Warning($"Missing registration for command {command}");
|
Plugin.Log.Warning($"Missing registration for command {command}");
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using ChatTwo.Code;
|
using ChatTwo.Code;
|
||||||
using ChatTwo.GameFunctions.Types;
|
using ChatTwo.GameFunctions.Types;
|
||||||
using ChatTwo.Resources;
|
using ChatTwo.Resources;
|
||||||
|
|||||||
@@ -478,12 +478,20 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
|
|
||||||
internal void SendTell(TellReason reason, ulong contentId, string name, ushort homeWorld, byte[] message, string rawText)
|
internal void SendTell(TellReason reason, ulong contentId, string name, ushort homeWorld, byte[] message, string rawText)
|
||||||
{
|
{
|
||||||
|
if (contentId == 0)
|
||||||
|
{
|
||||||
|
Plugin.ChatGui.PrintError(Language.Chat_SendTell_Error);
|
||||||
|
Plugin.Log.Warning("Tried to send a tell with ContentId being 0, sorry this is an internal error.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var uName = Utf8String.FromString(name);
|
var uName = Utf8String.FromString(name);
|
||||||
var uMessage = Utf8String.FromSequence(message);
|
var uMessage = Utf8String.FromSequence(message);
|
||||||
|
|
||||||
var encoded = Utf8String.FromUtf8String(PronounModule.Instance()->ProcessString(uMessage, true));
|
var encoded = Utf8String.FromUtf8String(PronounModule.Instance()->ProcessString(uMessage, true));
|
||||||
var decoded = EncodeMessage(rawText);
|
var decoded = EncodeMessage(rawText);
|
||||||
AutoTranslate.ReplaceWithPayload(ref decoded);
|
AutoTranslate.ReplaceWithPayload(ref decoded);
|
||||||
|
|
||||||
using var decodedUtf8String = new Utf8String(decoded);
|
using var decodedUtf8String = new Utf8String(decoded);
|
||||||
|
|
||||||
var logModule = RaptureLogModule.Instance();
|
var logModule = RaptureLogModule.Instance();
|
||||||
@@ -493,25 +501,11 @@ internal sealed unsafe class Chat : IDisposable
|
|||||||
if (reason == TellReason.Direct)
|
if (reason == TellReason.Direct)
|
||||||
reason = TellReason.Friend;
|
reason = TellReason.Friend;
|
||||||
|
|
||||||
if (contentId == 0)
|
|
||||||
{
|
|
||||||
encoded->Dtor(true);
|
|
||||||
uName->Dtor(true);
|
|
||||||
uMessage->Dtor(true);
|
|
||||||
|
|
||||||
Plugin.Log.Warning("Tried to send a tell with content id being 0");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok = SendTellNative(networkModule, contentId, homeWorld, uName, encoded, (ushort) reason, homeWorld);
|
var ok = SendTellNative(networkModule, contentId, homeWorld, uName, encoded, (ushort) reason, homeWorld);
|
||||||
if (ok == 1)
|
if (ok == 1)
|
||||||
{
|
|
||||||
PrintTellNative(logModule, 33, uName, &decodedUtf8String, 0, contentId, homeWorld, 255, 0, 0);
|
PrintTellNative(logModule, 33, uName, &decodedUtf8String, 0, contentId, homeWorld, 255, 0, 0);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
Plugin.ChatGui.PrintError(Language.Chat_SendTell_Error);
|
Plugin.ChatGui.PrintError(Language.Chat_SendTell_Error);
|
||||||
}
|
|
||||||
|
|
||||||
encoded->Dtor(true);
|
encoded->Dtor(true);
|
||||||
uName->Dtor(true);
|
uName->Dtor(true);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using FFXIVClientStructs.FFXIV.Client.UI;
|
|||||||
|
|
||||||
namespace ChatTwo.GameFunctions;
|
namespace ChatTwo.GameFunctions;
|
||||||
|
|
||||||
// From: https://git.anna.lgbt/anna/XivCommon/src/branch/main/XivCommon/Functions/Chat.cs
|
|
||||||
public unsafe class ChatBox
|
public unsafe class ChatBox
|
||||||
{
|
{
|
||||||
public static void SendMessageUnsafe(byte[] message)
|
public static void SendMessageUnsafe(byte[] message)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ internal sealed unsafe class Context
|
|||||||
|
|
||||||
internal static void TryOn(uint itemId, byte stainId)
|
internal static void TryOn(uint itemId, byte stainId)
|
||||||
{
|
{
|
||||||
AgentTryon.TryOn(0xFF, itemId, stainId, 0, 0);
|
AgentTryon.TryOn(0xFF, itemId, stainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void LinkItem(uint itemId)
|
internal static void LinkItem(uint itemId)
|
||||||
@@ -40,6 +40,6 @@ internal sealed unsafe class Context
|
|||||||
|
|
||||||
internal static void SearchForItem(uint itemId)
|
internal static void SearchForItem(uint itemId)
|
||||||
{
|
{
|
||||||
ItemFinderModule.Instance()->SearchForItem(itemId, true);
|
ItemFinderModule.Instance()->SearchForItem(itemId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ using System.Globalization;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
@@ -15,7 +14,6 @@ using FFXIVClientStructs.FFXIV.Client.UI.Info;
|
|||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
|
||||||
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
using ValueType = FFXIVClientStructs.FFXIV.Component.GUI.ValueType;
|
||||||
|
|
||||||
namespace ChatTwo.GameFunctions;
|
namespace ChatTwo.GameFunctions;
|
||||||
@@ -75,10 +73,9 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
|
|
||||||
private void ListCommand(string name, ushort world, string commandName)
|
private void ListCommand(string name, ushort world, string commandName)
|
||||||
{
|
{
|
||||||
var row = Plugin.DataManager.GetExcelSheet<World>().GetRow(world);
|
var worldRow = Sheets.WorldSheet.GetRow(world);
|
||||||
|
|
||||||
var worldName = row.Name.ExtractText();
|
ReplacementName = $"{name}@{worldRow.Name.ToString()}";
|
||||||
ReplacementName = $"{name}@{worldName}";
|
|
||||||
ChatBox.SendMessage($"/{commandName} add {Placeholder}");
|
ChatBox.SendMessage($"/{commandName} add {Placeholder}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +188,7 @@ internal unsafe class GameFunctions : IDisposable
|
|||||||
|
|
||||||
internal static void OpenQuestLog(RowRef<Quest> quest)
|
internal static void OpenQuestLog(RowRef<Quest> quest)
|
||||||
{
|
{
|
||||||
var splits = quest.Value.Id.ExtractText().Split("_");
|
var splits = quest.Value.Id.ToString().Split("_");
|
||||||
if (splits.Length != 2)
|
if (splits.Length != 2)
|
||||||
{
|
{
|
||||||
Plugin.ChatGui.Print("QuestId is wrongly formatted");
|
Plugin.ChatGui.Print("QuestId is wrongly formatted");
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ internal sealed class TellTarget
|
|||||||
|
|
||||||
public bool IsSet() => Name.Length > 0 && World > 0;
|
public bool IsSet() => Name.Length > 0 && World > 0;
|
||||||
|
|
||||||
public string ToWorldString() => Sheets.WorldSheet.TryGetRow(World, out var worldRow) ? worldRow.Name.ExtractText() : string.Empty;
|
public string ToWorldString() => Sheets.WorldSheet.TryGetRow(World, out var worldRow) ? worldRow.Name.ToString() : string.Empty;
|
||||||
public string ToTargetString() => $"{Name}@{ToWorldString()}";
|
public string ToTargetString() => $"{Name}@{ToWorldString()}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using ChatTwo.Http.MessageProtocol;
|
using ChatTwo.Http.MessageProtocol;
|
||||||
using ChatTwo.Util;
|
|
||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
|
|
||||||
namespace ChatTwo.Http;
|
namespace ChatTwo.Http;
|
||||||
@@ -25,7 +24,7 @@ public class ServerCore : IAsyncDisposable
|
|||||||
|
|
||||||
private void FrameworkUpdate(IFramework _)
|
private void FrameworkUpdate(IFramework _)
|
||||||
{
|
{
|
||||||
foreach (var (tab, idx) in Plugin.Config.Tabs.WithIndex())
|
foreach (var (idx, tab) in Plugin.Config.Tabs.Index())
|
||||||
{
|
{
|
||||||
if (tab.Unread == tab.LastSendUnread)
|
if (tab.Unread == tab.LastSendUnread)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -28,19 +28,16 @@ internal sealed class TypingIpc : IDisposable
|
|||||||
private ChatInputState BuildState()
|
private ChatInputState BuildState()
|
||||||
{
|
{
|
||||||
var log = Plugin.ChatLogWindow;
|
var log = Plugin.ChatLogWindow;
|
||||||
var chat = log.Chat ?? string.Empty;
|
|
||||||
var hasText = !string.IsNullOrWhiteSpace(chat);
|
var usedChannel = Plugin.CurrentTab.CurrentChannel;
|
||||||
var usedChannel = Plugin.CurrentTab?.CurrentChannel;
|
var inputChannel = usedChannel.UseTempChannel ? usedChannel.TempChannel : usedChannel.Channel;
|
||||||
var inputChannel = usedChannel is not null
|
|
||||||
? (usedChannel.UseTempChannel ? usedChannel.TempChannel : usedChannel.Channel)
|
|
||||||
: InputChannel.Invalid;
|
|
||||||
var channelType = inputChannel.ToChatType();
|
var channelType = inputChannel.ToChatType();
|
||||||
|
|
||||||
return (InputVisible: !log.IsHidden,
|
return (InputVisible: !log.IsHidden,
|
||||||
InputFocused: log.InputFocused,
|
InputFocused: log.InputFocused,
|
||||||
HasText: hasText,
|
HasText: log.Chat.Length > 0,
|
||||||
IsTyping: log.InputFocused && hasText,
|
IsTyping: log is { InputFocused: true, Chat.Length: > 0 },
|
||||||
TextLength: chat.Length,
|
TextLength: log.Chat.Length,
|
||||||
ChannelType: channelType);
|
ChannelType: channelType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -7,7 +7,6 @@ using System.Text.RegularExpressions;
|
|||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
||||||
using Lumina.Excel.Sheets;
|
|
||||||
|
|
||||||
namespace ChatTwo;
|
namespace ChatTwo;
|
||||||
|
|
||||||
@@ -234,7 +233,7 @@ internal partial class Message
|
|||||||
AddChunkWithMessage(text.NewWithStyle(chunk.Source, chunk.Link, sentenceBuilder.Append(!wordUsed ? word : "").ToString()));
|
AddChunkWithMessage(text.NewWithStyle(chunk.Source, chunk.Link, sentenceBuilder.Append(!wordUsed ? word : "").ToString()));
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
AddChunkWithMessage(text.NewWithStyle(chunk.Source, UriPayload.ResolveURI(token.Value), token.Value));
|
AddChunkWithMessage(text.NewWithStyle(chunk.Source, UriPayload.ResolveUri(token.Value), token.Value));
|
||||||
}
|
}
|
||||||
catch (UriFormatException)
|
catch (UriFormatException)
|
||||||
{
|
{
|
||||||
@@ -326,8 +325,8 @@ internal partial class Message
|
|||||||
};
|
};
|
||||||
|
|
||||||
var name = kind != ItemKind.EventItem
|
var name = kind != ItemKind.EventItem
|
||||||
? Plugin.DataManager.GetExcelSheet<Item>().GetRow(item.ItemId).Name.ToString()
|
? Sheets.ItemSheet.GetRow(item.ItemId).Name.ToString()
|
||||||
: Plugin.DataManager.GetExcelSheet<EventItem>().GetRow(item.ItemId).Name.ToString();
|
: Sheets.EventItemSheet.GetRow(item.ItemId).Name.ToString();
|
||||||
|
|
||||||
var link = new ItemPayload(item.ItemId, kind, $"{SeIconChar.LinkMarker.ToIconChar()}{name}");
|
var link = new ItemPayload(item.ItemId, kind, $"{SeIconChar.LinkMarker.ToIconChar()}{name}");
|
||||||
AddChunkWithMessage(text.NewWithStyle(chunk.Source, link, link.DisplayName ?? "Unknown"));
|
AddChunkWithMessage(text.NewWithStyle(chunk.Source, link, link.DisplayName ?? "Unknown"));
|
||||||
@@ -341,7 +340,7 @@ internal partial class Message
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nameValue = statusRow.Name.ToDalamudString().TextValue;
|
var nameValue = statusRow.Name.ToString();
|
||||||
var content = statusRow.StatusCategory switch
|
var content = statusRow.StatusCategory switch
|
||||||
{
|
{
|
||||||
1 => $"{SeIconChar.Buff.ToIconString()}{nameValue}",
|
1 => $"{SeIconChar.Buff.ToIconString()}{nameValue}",
|
||||||
|
|||||||
+26
-21
@@ -1,5 +1,6 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
using ChatTwo.Code;
|
using ChatTwo.Code;
|
||||||
using ChatTwo.Resources;
|
using ChatTwo.Resources;
|
||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
@@ -10,7 +11,9 @@ using Dalamud.Interface.ImGuiNotification;
|
|||||||
using Dalamud.Plugin.Services;
|
using Dalamud.Plugin.Services;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
using FFXIVClientStructs.FFXIV.Client.UI.Misc;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Text.Expressions;
|
||||||
|
using Lumina.Text.Payloads;
|
||||||
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
namespace ChatTwo;
|
namespace ChatTwo;
|
||||||
|
|
||||||
@@ -21,7 +24,7 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
private Plugin Plugin { get; }
|
private Plugin Plugin { get; }
|
||||||
internal MessageStore Store { get; }
|
internal MessageStore Store { get; }
|
||||||
|
|
||||||
private Dictionary<ChatType, NameFormatting> Formats { get; } = new();
|
private Dictionary<ChatType, NameFormatting> Formats { get; } = [];
|
||||||
private ulong LastContentId { get; set; }
|
private ulong LastContentId { get; set; }
|
||||||
|
|
||||||
// Messages go into the PendingSync queue first, which will be consumed one
|
// Messages go into the PendingSync queue first, which will be consumed one
|
||||||
@@ -31,8 +34,8 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
// After that, the message is enqueued in the PendingAsync queue, which will
|
// After that, the message is enqueued in the PendingAsync queue, which will
|
||||||
// be consumed in a separate thread and perform more processing (emotes,
|
// be consumed in a separate thread and perform more processing (emotes,
|
||||||
// URLs) as well as inserting the message into the database.
|
// URLs) as well as inserting the message into the database.
|
||||||
private Queue<PendingMessage> PendingSync { get; } = new();
|
private Queue<PendingMessage> PendingSync { get; } = [];
|
||||||
private ConcurrentQueue<PendingMessage> PendingAsync { get; } = new();
|
private ConcurrentQueue<PendingMessage> PendingAsync { get; } = [];
|
||||||
private readonly Thread PendingMessageThread;
|
private readonly Thread PendingMessageThread;
|
||||||
private readonly CancellationTokenSource PendingThreadCancellationToken = new();
|
private readonly CancellationTokenSource PendingThreadCancellationToken = new();
|
||||||
|
|
||||||
@@ -298,36 +301,38 @@ internal class MessageManager : IAsyncDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private NameFormatting? FormatFor(ChatType type)
|
private NameFormatting FormatFor(ChatType type)
|
||||||
{
|
{
|
||||||
if (Formats.TryGetValue(type, out var cached))
|
if (Formats.TryGetValue(type, out var cached))
|
||||||
return cached;
|
return cached;
|
||||||
|
|
||||||
var logKind = Plugin.DataManager.GetExcelSheet<LogKind>().GetRow((ushort)type);
|
var formats = Sheets.LogKindSheet.GetRow((uint)type).Format.ToList();
|
||||||
var format = logKind.Format.ToDalamudString();
|
static bool IsStringParam(ReadOnlySePayload payload, byte num)
|
||||||
|
|
||||||
static bool IsStringParam(Payload payload, byte num)
|
|
||||||
{
|
{
|
||||||
var data = payload.Encode();
|
if (payload.MacroCode != MacroCode.String)
|
||||||
return data.Length >= 5 && data[1] == 0x29 && data[4] == num + 1;
|
return false;
|
||||||
|
|
||||||
|
return payload.TryGetExpression(out var expr1)
|
||||||
|
&& expr1.TryGetParameterExpression(out var expressionType, out var operand)
|
||||||
|
&& expressionType == (byte)ExpressionType.LocalString
|
||||||
|
&& operand.TryGetInt(out var lstrIndex)
|
||||||
|
&& lstrIndex == num;
|
||||||
}
|
}
|
||||||
|
|
||||||
var firstStringParam = format.Payloads.FindIndex(payload => IsStringParam(payload, 1));
|
var firstStringParam = formats.FindIndex(payload => IsStringParam(payload, 1));
|
||||||
var secondStringParam = format.Payloads.FindIndex(payload => IsStringParam(payload, 2));
|
var secondStringParam = formats.FindIndex(payload => IsStringParam(payload, 2));
|
||||||
|
|
||||||
if (firstStringParam == -1 || secondStringParam == -1)
|
if (firstStringParam == -1 || secondStringParam == -1)
|
||||||
return NameFormatting.Empty();
|
return NameFormatting.Empty();
|
||||||
|
|
||||||
var before = format.Payloads
|
var before = formats
|
||||||
.GetRange(0, firstStringParam)
|
.GetRange(0, firstStringParam)
|
||||||
.Where(payload => payload is ITextProvider)
|
.Where(payload => payload.Type == ReadOnlySePayloadType.Text)
|
||||||
.Cast<ITextProvider>()
|
.Select(text => Encoding.UTF8.GetString(text.Body.Span));
|
||||||
.Select(text => text.Text);
|
var after = formats
|
||||||
var after = format.Payloads
|
|
||||||
.GetRange(firstStringParam + 1, secondStringParam - firstStringParam)
|
.GetRange(firstStringParam + 1, secondStringParam - firstStringParam)
|
||||||
.Where(payload => payload is ITextProvider)
|
.Where(payload => payload.Type == ReadOnlySePayloadType.Text)
|
||||||
.Cast<ITextProvider>()
|
.Select(text => Encoding.UTF8.GetString(text.Body.Span)); // Can't use `ToString()` as it defaults to macro
|
||||||
.Select(text => text.Text);
|
|
||||||
|
|
||||||
var nameFormatting = NameFormatting.Of(string.Join("", before), string.Join("", after));
|
var nameFormatting = NameFormatting.Of(string.Join("", before), string.Join("", after));
|
||||||
Formats[type] = nameFormatting;
|
Formats[type] = nameFormatting;
|
||||||
|
|||||||
+21
-23
@@ -20,7 +20,6 @@ using FFXIVClientStructs.FFXIV.Client.UI;
|
|||||||
using FFXIVClientStructs.FFXIV.Component.GUI;
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
|
||||||
using Action = System.Action;
|
using Action = System.Action;
|
||||||
using DalamudPartyFinderPayload = Dalamud.Game.Text.SeStringHandling.Payloads.PartyFinderPayload;
|
using DalamudPartyFinderPayload = Dalamud.Game.Text.SeStringHandling.Payloads.PartyFinderPayload;
|
||||||
using ChatTwoPartyFinderPayload = ChatTwo.Util.PartyFinderPayload;
|
using ChatTwoPartyFinderPayload = ChatTwo.Util.PartyFinderPayload;
|
||||||
@@ -39,7 +38,7 @@ public sealed class PayloadHandler
|
|||||||
public uint HoverCounter;
|
public uint HoverCounter;
|
||||||
public uint LastHoverCounter;
|
public uint LastHoverCounter;
|
||||||
|
|
||||||
private const uint PopupSfx = 1u;
|
private const uint PopupSfx = 1;
|
||||||
|
|
||||||
internal PayloadHandler(ChatLogWindow logWindow)
|
internal PayloadHandler(ChatLogWindow logWindow)
|
||||||
{
|
{
|
||||||
@@ -110,7 +109,7 @@ public sealed class PayloadHandler
|
|||||||
var contentId = chunk.Message?.ContentId ?? 0;
|
var contentId = chunk.Message?.ContentId ?? 0;
|
||||||
var sender = chunk.Message?.Sender.Select(c => c.Link).FirstOrDefault(p => p is PlayerPayload) as PlayerPayload;
|
var sender = chunk.Message?.Sender.Select(c => c.Link).FirstOrDefault(p => p is PlayerPayload) as PlayerPayload;
|
||||||
|
|
||||||
using var menu = ImGuiUtil.Menu(Language.Context_Integrations);
|
using var menu = ImRaii.Menu(Language.Context_Integrations);
|
||||||
if (!menu.Success)
|
if (!menu.Success)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -146,7 +145,7 @@ public sealed class PayloadHandler
|
|||||||
//
|
//
|
||||||
// It makes it much more convenient in the majority of cases to
|
// It makes it much more convenient in the majority of cases to
|
||||||
// copy the message content without having to open a submenu.
|
// copy the message content without having to open a submenu.
|
||||||
menu = ImGuiUtil.Menu(Plugin.PluginName);
|
menu = ImRaii.Menu(Plugin.PluginName);
|
||||||
if (!menu.Success)
|
if (!menu.Success)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -240,7 +239,7 @@ public sealed class PayloadHandler
|
|||||||
DoHover(() => HoverItem(item), hoverSize);
|
DoHover(() => HoverItem(item), hoverSize);
|
||||||
break;
|
break;
|
||||||
case UriPayload uri:
|
case UriPayload uri:
|
||||||
DoHover(() => HoverURI(uri), hoverSize);
|
DoHover(() => HoverUri(uri), hoverSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,16 +249,14 @@ public sealed class PayloadHandler
|
|||||||
ImGui.SetNextWindowSize(new Vector2(width, -1f));
|
ImGui.SetNextWindowSize(new Vector2(width, -1f));
|
||||||
|
|
||||||
using (ImRaii.Tooltip())
|
using (ImRaii.Tooltip())
|
||||||
using (ImGuiUtil.TextWrapPos())
|
using (ImRaii.TextWrapPos(0.0f))
|
||||||
using (ImRaii.PushColor(ImGuiCol.Text, LogWindow.DefaultText))
|
using (ImRaii.PushColor(ImGuiCol.Text, LogWindow.DefaultText))
|
||||||
{
|
|
||||||
inside();
|
inside();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public unsafe void MoveTooltip(AddonEvent type, AddonArgs args)
|
public unsafe void MoveTooltip(AddonEvent type, AddonArgs args)
|
||||||
{
|
{
|
||||||
// Only move if user has "Next to Cursor" option selected
|
// Only move if the user has the "Next to Cursor" option selected
|
||||||
if (!Plugin.GameConfig.TryGet(UiControlOption.DetailTrackingType, out uint selected) || selected != 0)
|
if (!Plugin.GameConfig.TryGet(UiControlOption.DetailTrackingType, out uint selected) || selected != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -352,7 +349,7 @@ public sealed class PayloadHandler
|
|||||||
InlineIcon(icon);
|
InlineIcon(icon);
|
||||||
|
|
||||||
var builder = new SeStringBuilder();
|
var builder = new SeStringBuilder();
|
||||||
var nameValue = status.Status.Value.Name.ToDalamudString().TextValue;
|
var nameValue = status.Status.Value.Name.ToString();
|
||||||
switch (status.Status.Value.StatusCategory)
|
switch (status.Status.Value.StatusCategory)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
@@ -364,14 +361,13 @@ public sealed class PayloadHandler
|
|||||||
default:
|
default:
|
||||||
builder.AddUiForeground(nameValue, 1);
|
builder.AddUiForeground(nameValue, 1);
|
||||||
break;
|
break;
|
||||||
};
|
}
|
||||||
|
|
||||||
var name = ChunkUtil.ToChunks(builder.BuiltString, ChunkSource.None, null);
|
var name = ChunkUtil.ToChunks(builder.BuiltString, ChunkSource.None, null);
|
||||||
LogWindow.DrawChunks(name.ToList());
|
LogWindow.DrawChunks(name.ToList());
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
var descString = status.Status.Value.Description.ToDalamudString();
|
var desc = ChunkUtil.ToChunks(status.Status.Value.Description.ToDalamudString(), ChunkSource.None, null);
|
||||||
var desc = ChunkUtil.ToChunks(descString, ChunkSource.None, null);
|
|
||||||
LogWindow.DrawChunks(desc.ToList());
|
LogWindow.DrawChunks(desc.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -383,7 +379,9 @@ public sealed class PayloadHandler
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
item.Item.TryGetValue(out Item resolvedItem);
|
if (!item.Item.TryGetValue(out Item resolvedItem))
|
||||||
|
return;
|
||||||
|
|
||||||
if (Plugin.TextureProvider.GetFromGameIcon(new GameIconLookup(resolvedItem.Icon, item.IsHQ)).GetWrapOrDefault() is { } icon)
|
if (Plugin.TextureProvider.GetFromGameIcon(new GameIconLookup(resolvedItem.Icon, item.IsHQ)).GetWrapOrDefault() is { } icon)
|
||||||
InlineIcon(icon);
|
InlineIcon(icon);
|
||||||
|
|
||||||
@@ -413,7 +411,7 @@ public sealed class PayloadHandler
|
|||||||
LogWindow.DrawChunks(ChunkUtil.ToChunks(itemHelpRow.Description.ToDalamudString(), ChunkSource.None, null).ToList());
|
LogWindow.DrawChunks(ChunkUtil.ToChunks(itemHelpRow.Description.ToDalamudString(), ChunkSource.None, null).ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HoverURI(UriPayload uri)
|
private void HoverUri(UriPayload uri)
|
||||||
{
|
{
|
||||||
ImGui.TextUnformatted(string.Format(Language.Context_URLDomain, uri.Uri.Authority));
|
ImGui.TextUnformatted(string.Format(Language.Context_URLDomain, uri.Uri.Authority));
|
||||||
ImGuiUtil.WarningText(Language.Context_URLWarning);
|
ImGuiUtil.WarningText(Language.Context_URLWarning);
|
||||||
@@ -449,7 +447,7 @@ public sealed class PayloadHandler
|
|||||||
GameFunctions.GameFunctions.OpenPartyFinder();
|
GameFunctions.GameFunctions.OpenPartyFinder();
|
||||||
break;
|
break;
|
||||||
case UriPayload uri:
|
case UriPayload uri:
|
||||||
WrapperUtil.TryOpenURI(uri.Uri);
|
WrapperUtil.TryOpenUri(uri.Uri);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
RightClickPayload(chunk, payload);
|
RightClickPayload(chunk, payload);
|
||||||
@@ -552,8 +550,7 @@ public sealed class PayloadHandler
|
|||||||
if (Plugin.TextureProvider.GetFromGameIcon(new GameIconLookup(item.Icon)).GetWrapOrDefault() is { } icon)
|
if (Plugin.TextureProvider.GetFromGameIcon(new GameIconLookup(item.Icon)).GetWrapOrDefault() is { } icon)
|
||||||
InlineIcon(icon);
|
InlineIcon(icon);
|
||||||
|
|
||||||
var name = item.Name.ToDalamudString();
|
LogWindow.DrawChunks(ChunkUtil.ToChunks(item.Name.ToDalamudString(), ChunkSource.None, null).ToList(), false);
|
||||||
LogWindow.DrawChunks(ChunkUtil.ToChunks(name, ChunkSource.None, null).ToList(), false);
|
|
||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
var realItemId = payload.RawItemId;
|
var realItemId = payload.RawItemId;
|
||||||
@@ -561,12 +558,13 @@ public sealed class PayloadHandler
|
|||||||
GameFunctions.Context.LinkItem(realItemId);
|
GameFunctions.Context.LinkItem(realItemId);
|
||||||
|
|
||||||
if (ImGui.Selectable(Language.Context_CopyItemName))
|
if (ImGui.Selectable(Language.Context_CopyItemName))
|
||||||
ImGui.SetClipboardText(name.TextValue);
|
ImGui.SetClipboardText(item.Name.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DrawPlayerPopup(Chunk chunk, PlayerPayload player)
|
private void DrawPlayerPopup(Chunk chunk, PlayerPayload player)
|
||||||
{
|
{
|
||||||
// Possible that GMs return a null payload
|
// Possible that GMs return a null payload
|
||||||
|
// ReSharper disable once ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract
|
||||||
if (player == null)
|
if (player == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -627,7 +625,7 @@ public sealed class PayloadHandler
|
|||||||
}
|
}
|
||||||
else if (!inInstance)
|
else if (!inInstance)
|
||||||
{
|
{
|
||||||
using var menu = ImGuiUtil.Menu(Language.Context_InviteToParty);
|
using var menu = ImRaii.Menu(Language.Context_InviteToParty);
|
||||||
if (menu.Success)
|
if (menu.Success)
|
||||||
{
|
{
|
||||||
if (ImGui.Selectable(Language.Context_InviteToParty_SameWorld))
|
if (ImGui.Selectable(Language.Context_InviteToParty_SameWorld))
|
||||||
@@ -653,7 +651,7 @@ public sealed class PayloadHandler
|
|||||||
if (!isFriend && ImGui.Selectable(Language.Context_SendFriendRequest))
|
if (!isFriend && ImGui.Selectable(Language.Context_SendFriendRequest))
|
||||||
LogWindow.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) world.RowId);
|
LogWindow.Plugin.Functions.SendFriendRequest(player.PlayerName, (ushort) world.RowId);
|
||||||
|
|
||||||
using (var menuBlockFunctions = ImGuiUtil.Menu(Language.Context_BlockFunctions))
|
using (var menuBlockFunctions = ImRaii.Menu(Language.Context_BlockFunctions))
|
||||||
{
|
{
|
||||||
if (menuBlockFunctions.Success)
|
if (menuBlockFunctions.Success)
|
||||||
{
|
{
|
||||||
@@ -718,7 +716,7 @@ public sealed class PayloadHandler
|
|||||||
ImGui.Separator();
|
ImGui.Separator();
|
||||||
|
|
||||||
if (ImGui.Selectable(Language.Context_OpenInBrowser))
|
if (ImGui.Selectable(Language.Context_OpenInBrowser))
|
||||||
WrapperUtil.TryOpenURI(uri.Uri);
|
WrapperUtil.TryOpenUri(uri.Uri);
|
||||||
|
|
||||||
if (ImGui.Selectable(Language.Context_CopyLink))
|
if (ImGui.Selectable(Language.Context_CopyLink))
|
||||||
{
|
{
|
||||||
@@ -733,7 +731,7 @@ public sealed class PayloadHandler
|
|||||||
InlineIcon(icon);
|
InlineIcon(icon);
|
||||||
|
|
||||||
var builder = new SeStringBuilder();
|
var builder = new SeStringBuilder();
|
||||||
var nameValue = status.Status.Value.Name.ToDalamudString().TextValue;
|
var nameValue = status.Status.Value.Name.ToString();
|
||||||
switch (status.Status.Value.StatusCategory)
|
switch (status.Status.Value.StatusCategory)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
|
|||||||
+4
-6
@@ -7,7 +7,6 @@ using ChatTwo.Resources;
|
|||||||
using ChatTwo.Ui;
|
using ChatTwo.Ui;
|
||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using Dalamud.Game.ClientState.Conditions;
|
using Dalamud.Game.ClientState.Conditions;
|
||||||
using Dalamud.Game.ClientState.Objects;
|
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.IoC;
|
using Dalamud.IoC;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
@@ -40,6 +39,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
[PluginService] internal static INotificationManager Notification { get; private set; } = null!;
|
[PluginService] internal static INotificationManager Notification { get; private set; } = null!;
|
||||||
[PluginService] internal static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
|
[PluginService] internal static IAddonLifecycle AddonLifecycle { get; private set; } = null!;
|
||||||
[PluginService] internal static IPlayerState PlayerState { get; private set; } = null!;
|
[PluginService] internal static IPlayerState PlayerState { get; private set; } = null!;
|
||||||
|
[PluginService] internal static ISeStringEvaluator Evaluator { get; private set; } = null!;
|
||||||
|
|
||||||
internal static Configuration Config = null!;
|
internal static Configuration Config = null!;
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
// Functions calls this in its ctor if the player is already logged in
|
// Functions calls this in its ctor if the player is already logged in
|
||||||
ServerCore = new ServerCore(this);
|
ServerCore = new ServerCore(this);
|
||||||
|
|
||||||
Commands = new Commands(this);
|
Commands = new Commands();
|
||||||
Functions = new GameFunctions.GameFunctions(this);
|
Functions = new GameFunctions.GameFunctions(this);
|
||||||
Ipc = new IpcManager();
|
Ipc = new IpcManager();
|
||||||
TypingIpc = new TypingIpc(this);
|
TypingIpc = new TypingIpc(this);
|
||||||
@@ -202,7 +202,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
if (Config.HideInLoadingScreens && Condition[ConditionFlag.BetweenAreas])
|
if (Config.HideInLoadingScreens && Condition[ConditionFlag.BetweenAreas])
|
||||||
{
|
{
|
||||||
ChatLogWindow.FinalizeFrame();
|
ChatLogWindow.FinalizeFrame();
|
||||||
TypingIpc?.Update();
|
TypingIpc.Update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,12 +212,10 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
ChatLogWindow.DefaultText = ImGui.GetStyle().Colors[(int) ImGuiCol.Text];
|
ChatLogWindow.DefaultText = ImGui.GetStyle().Colors[(int) ImGuiCol.Text];
|
||||||
|
|
||||||
using ((Config.FontsEnabled ? FontManager.RegularFont : FontManager.Axis).Push())
|
using ((Config.FontsEnabled ? FontManager.RegularFont : FontManager.Axis).Push())
|
||||||
{
|
|
||||||
WindowSystem.Draw();
|
WindowSystem.Draw();
|
||||||
}
|
|
||||||
|
|
||||||
ChatLogWindow.FinalizeFrame();
|
ChatLogWindow.FinalizeFrame();
|
||||||
TypingIpc?.Update();
|
TypingIpc.Update();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void SaveConfig()
|
internal void SaveConfig()
|
||||||
|
|||||||
Generated
+1
-1
@@ -402,7 +402,7 @@ Sie wurden gewarnt.</value>
|
|||||||
<value>{0} ist ein Projekt, dessen Ziel es ist, den Spielchat zu verbessern und neu zu gestalten.</value>
|
<value>{0} ist ein Projekt, dessen Ziel es ist, den Spielchat zu verbessern und neu zu gestalten.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>Drücken Sie auf den linken Knopf, um bei der Übersetzung von {0} zu helfen.</value>
|
<value>Helfen Sie bei der Übersetzung: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>Übersetzer</value>
|
<value>Übersetzer</value>
|
||||||
|
|||||||
Generated
+8
-8
@@ -401,7 +401,7 @@
|
|||||||
<value>{0} est un projet visant à recréer complètement le chat en jeu et à l'améliorer.</value>
|
<value>{0} est un projet visant à recréer complètement le chat en jeu et à l'améliorer.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>Cliquez sur le bouton à gauche pour nous aider à traduire {0}.</value>
|
<value>Help to translate: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>Traducteurs</value>
|
<value>Traducteurs</value>
|
||||||
@@ -542,7 +542,7 @@
|
|||||||
<value>Opacité</value>
|
<value>Opacité</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_Tabs_IndependentHide">
|
<data name="Options_Tabs_IndependentHide">
|
||||||
<value>Use different hide condition than main window</value>
|
<value>Utiliser une condition de masquage différente de la fenêtre principale</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_FontsEnabled">
|
<data name="Options_FontsEnabled">
|
||||||
<value>Activer les fontes personnalisées</value>
|
<value>Activer les fontes personnalisées</value>
|
||||||
@@ -680,7 +680,7 @@
|
|||||||
<value>Inviter dans l'équipe</value>
|
<value>Inviter dans l'équipe</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Context_BlockFunctions">
|
<data name="Context_BlockFunctions">
|
||||||
<value>Block Functions</value>
|
<value>Fonctions de blocage</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Context_InviteToParty_SameWorld">
|
<data name="Context_InviteToParty_SameWorld">
|
||||||
<value>Même monde</value>
|
<value>Même monde</value>
|
||||||
@@ -701,10 +701,10 @@
|
|||||||
<value>Ajouter à la liste noire</value>
|
<value>Ajouter à la liste noire</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Context_AddToMuteList">
|
<data name="Context_AddToMuteList">
|
||||||
<value>Register to Mute List</value>
|
<value>Ajouter à la Liste Muette</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Context_AddToTermsFilter">
|
<data name="Context_AddToTermsFilter">
|
||||||
<value>Add to Term Filters</value>
|
<value>Ajouter aux filtres des termes</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Context_InviteToNoviceNetwork">
|
<data name="Context_InviteToNoviceNetwork">
|
||||||
<value>Inviter dans le réseau des novices</value>
|
<value>Inviter dans le réseau des novices</value>
|
||||||
@@ -842,7 +842,7 @@
|
|||||||
<value>Notifications d'alarme</value>
|
<value>Notifications d'alarme</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_Glamour">
|
<data name="ChatType_Glamour">
|
||||||
<value>Glamour Notifications</value>
|
<value>Notification de Glamour</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_Echo">
|
<data name="ChatType_Echo">
|
||||||
<value>Écho</value>
|
<value>Écho</value>
|
||||||
@@ -965,10 +965,10 @@
|
|||||||
<value>Remplace les messages identiques consécutifs par un compteur ajouté à la première instance des dits messages.</value>
|
<value>Remplace les messages identiques consécutifs par un compteur ajouté à la première instance des dits messages.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_CollapseDuplicateMsgUniqueLink_Name">
|
<data name="Options_CollapseDuplicateMsgUniqueLink_Name">
|
||||||
<value>Keep unique links seperate</value>
|
<value>Garder les liens uniques séparés</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_CollapseDuplicateMsgUniqueLink_Description">
|
<data name="Options_CollapseDuplicateMsgUniqueLink_Description">
|
||||||
<value>Don't collapse messages if they link to different things with the same text.</value>
|
<value>Ne pas réduire les messages s'ils sont liés à des choses différentes avec le même texte.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_Tabs_ExtraChatChannels">
|
<data name="Options_Tabs_ExtraChatChannels">
|
||||||
<value>Canaux d'ExtraChat</value>
|
<value>Canaux d'ExtraChat</value>
|
||||||
|
|||||||
Generated
+3
-3
@@ -827,7 +827,7 @@
|
|||||||
<value>回復</value>
|
<value>回復</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_GainBuff">
|
<data name="ChatType_GainBuff">
|
||||||
<value></value>
|
<value>Beneficial effects granted</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_GainDebuff">
|
<data name="ChatType_GainDebuff">
|
||||||
<value>Detrimental effects inflicted</value>
|
<value>Detrimental effects inflicted</value>
|
||||||
@@ -893,10 +893,10 @@
|
|||||||
<value>PT募集通知</value>
|
<value>PT募集通知</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_Sign">
|
<data name="ChatType_Sign">
|
||||||
<value></value>
|
<value>Sign Messages for PC Targets</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_RandomNumber">
|
<data name="ChatType_RandomNumber">
|
||||||
<value></value>
|
<value>Random Number Messages</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ChatType_NoviceNetworkSystem">
|
<data name="ChatType_NoviceNetworkSystem">
|
||||||
<value>ビギナーチャンネルアナウンス</value>
|
<value>ビギナーチャンネルアナウンス</value>
|
||||||
|
|||||||
Generated
+1
-1
@@ -401,7 +401,7 @@
|
|||||||
<value>{0} is een project om de in-game chat volledig opnieuw te maken en nog beter te maken.</value>
|
<value>{0} is een project om de in-game chat volledig opnieuw te maken en nog beter te maken.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>Klik op de knop links om {0} te helpen vertalen.</value>
|
<value>Help to translate: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>Vertalers</value>
|
<value>Vertalers</value>
|
||||||
|
|||||||
Generated
+1
-1
@@ -401,7 +401,7 @@
|
|||||||
<value>{0} este un proiect care recreează complet chat-ul din joc si îl îmbunătățește.</value>
|
<value>{0} este un proiect care recreează complet chat-ul din joc si îl îmbunătățește.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>Apasă butonul din stânga pentru a contribui la traducerea {0}.</value>
|
<value>Help to translate: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>Traducători</value>
|
<value>Traducători</value>
|
||||||
|
|||||||
Generated
+1
-1
@@ -401,7 +401,7 @@
|
|||||||
<value>{0} - проект, полностью пересоздаёт внутриигровой чат и делает его еще лучше.</value>
|
<value>{0} - проект, полностью пересоздаёт внутриигровой чат и делает его еще лучше.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>Нажмите кнопку слева, чтобы помочь перевести {0}.</value>
|
<value>Help to translate: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>Переводчики</value>
|
<value>Переводчики</value>
|
||||||
|
|||||||
Generated
+2
-2
@@ -395,13 +395,13 @@
|
|||||||
<value>Ny flik</value>
|
<value>Ny flik</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Tab">
|
<data name="Options_About_Tab">
|
||||||
<value>Om {0}</value>
|
<value>Om</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Opening">
|
<data name="Options_About_Opening">
|
||||||
<value>{0} är ett projekt gjort för att fullt återskapa spelets ursprungliga chattfönster och göra det ännu bättre.</value>
|
<value>{0} är ett projekt gjort för att fullt återskapa spelets ursprungliga chattfönster och göra det ännu bättre.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>Klicka på knappen till vänster för att hjälpa med översättningen av {0}.</value>
|
<value>Help to translate: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>Översättare</value>
|
<value>Översättare</value>
|
||||||
|
|||||||
Generated
+1
-1
@@ -402,7 +402,7 @@
|
|||||||
繁體中文是為了不開補全功能也能與其他玩家正常顯示溝通所翻譯及修改。</value>
|
繁體中文是為了不開補全功能也能與其他玩家正常顯示溝通所翻譯及修改。</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_CrowdIn">
|
<data name="Options_About_CrowdIn">
|
||||||
<value>點選左邊的按鈕來幇助翻譯 {0}。</value>
|
<value>Help to translate: </value>
|
||||||
</data>
|
</data>
|
||||||
<data name="Options_About_Translators">
|
<data name="Options_About_Translators">
|
||||||
<value>翻譯人員</value>
|
<value>翻譯人員</value>
|
||||||
|
|||||||
+5
-1
@@ -8,6 +8,8 @@ public static class Sheets
|
|||||||
public static readonly ExcelSheet<Item> ItemSheet;
|
public static readonly ExcelSheet<Item> ItemSheet;
|
||||||
public static readonly ExcelSheet<World> WorldSheet;
|
public static readonly ExcelSheet<World> WorldSheet;
|
||||||
public static readonly ExcelSheet<Status> StatusSheet;
|
public static readonly ExcelSheet<Status> StatusSheet;
|
||||||
|
public static readonly ExcelSheet<UIColor> UIColorSheet;
|
||||||
|
public static readonly ExcelSheet<LogKind> LogKindSheet;
|
||||||
public static readonly ExcelSheet<LogFilter> LogFilterSheet;
|
public static readonly ExcelSheet<LogFilter> LogFilterSheet;
|
||||||
public static readonly ExcelSheet<EventItem> EventItemSheet;
|
public static readonly ExcelSheet<EventItem> EventItemSheet;
|
||||||
public static readonly ExcelSheet<Completion> CompletionSheet;
|
public static readonly ExcelSheet<Completion> CompletionSheet;
|
||||||
@@ -20,8 +22,10 @@ public static class Sheets
|
|||||||
ItemSheet = Plugin.DataManager.GetExcelSheet<Item>();
|
ItemSheet = Plugin.DataManager.GetExcelSheet<Item>();
|
||||||
WorldSheet = Plugin.DataManager.GetExcelSheet<World>();
|
WorldSheet = Plugin.DataManager.GetExcelSheet<World>();
|
||||||
StatusSheet = Plugin.DataManager.GetExcelSheet<Status>();
|
StatusSheet = Plugin.DataManager.GetExcelSheet<Status>();
|
||||||
EventItemSheet = Plugin.DataManager.GetExcelSheet<EventItem>();
|
UIColorSheet = Plugin.DataManager.GetExcelSheet<UIColor>();
|
||||||
|
LogKindSheet = Plugin.DataManager.GetExcelSheet<LogKind>();
|
||||||
LogFilterSheet = Plugin.DataManager.GetExcelSheet<LogFilter>();
|
LogFilterSheet = Plugin.DataManager.GetExcelSheet<LogFilter>();
|
||||||
|
EventItemSheet = Plugin.DataManager.GetExcelSheet<EventItem>();
|
||||||
CompletionSheet = Plugin.DataManager.GetExcelSheet<Completion>();
|
CompletionSheet = Plugin.DataManager.GetExcelSheet<Completion>();
|
||||||
TerritorySheet = Plugin.DataManager.GetExcelSheet<TerritoryType>();
|
TerritorySheet = Plugin.DataManager.GetExcelSheet<TerritoryType>();
|
||||||
TextCommandSheet = Plugin.DataManager.GetExcelSheet<TextCommand>();
|
TextCommandSheet = Plugin.DataManager.GetExcelSheet<TextCommand>();
|
||||||
|
|||||||
+45
-29
@@ -20,6 +20,7 @@ using Dalamud.Memory;
|
|||||||
using FFXIVClientStructs.FFXIV.Client.UI;
|
using FFXIVClientStructs.FFXIV.Client.UI;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Excel.Sheets;
|
||||||
|
using Lumina.Extensions;
|
||||||
|
|
||||||
namespace ChatTwo.Ui;
|
namespace ChatTwo.Ui;
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
public PayloadHandler PayloadHandler { get; }
|
public PayloadHandler PayloadHandler { get; }
|
||||||
internal Lender<PayloadHandler> HandlerLender { get; }
|
internal Lender<PayloadHandler> HandlerLender { get; }
|
||||||
private Dictionary<string, ChatType> TextCommandChannels { get; } = new();
|
private Dictionary<string, ChatType> TextCommandChannels { get; } = new();
|
||||||
private HashSet<string> AllCommands { get; } = [];
|
private Dictionary<string, TextCommand> AllCommands { get; } = [];
|
||||||
|
|
||||||
private const uint ChatOpenSfx = 35u;
|
private const uint ChatOpenSfx = 35u;
|
||||||
private const uint ChatCloseSfx = 3u;
|
private const uint ChatCloseSfx = 3u;
|
||||||
@@ -238,7 +239,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
|
|
||||||
private bool IsValidCommand(string command)
|
private bool IsValidCommand(string command)
|
||||||
{
|
{
|
||||||
return Plugin.CommandManager.Commands.ContainsKey(command) || AllCommands.Contains(command);
|
return Plugin.CommandManager.Commands.ContainsKey(command) || AllCommands.ContainsKey(command);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearLog(string command, string arguments)
|
private void ClearLog(string command, string arguments)
|
||||||
@@ -288,7 +289,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
|
|
||||||
foreach (var input in Enum.GetValues<InputChannel>())
|
foreach (var input in Enum.GetValues<InputChannel>())
|
||||||
{
|
{
|
||||||
var commands = input.TextCommands(Plugin.DataManager);
|
var commands = input.TextCommands();
|
||||||
if (commands == null)
|
if (commands == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -297,11 +298,8 @@ public sealed class ChatLogWindow : Window
|
|||||||
AddTextCommandChannel(command, type);
|
AddTextCommandChannel(command, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Sheets.TextCommandSheet.HasRow(116))
|
if (Sheets.TextCommandSheet.TryGetRow(116, out var row))
|
||||||
{
|
AddTextCommandChannel(row, ChatType.Echo);
|
||||||
var echo = Sheets.TextCommandSheet.GetRow(116);
|
|
||||||
AddTextCommandChannel(echo, ChatType.Echo);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddTextCommandChannel(TextCommand command, ChatType type)
|
private void AddTextCommandChannel(TextCommand command, ChatType type)
|
||||||
@@ -314,19 +312,20 @@ public sealed class ChatLogWindow : Window
|
|||||||
|
|
||||||
private void SetUpAllCommands()
|
private void SetUpAllCommands()
|
||||||
{
|
{
|
||||||
if (Plugin.DataManager.GetExcelSheet<TextCommand>() is not { } commands)
|
foreach (var command in Sheets.TextCommandSheet)
|
||||||
return;
|
|
||||||
|
|
||||||
var commandNames = commands.SelectMany(cmd => new[]
|
|
||||||
{
|
{
|
||||||
cmd.Command.ExtractText(),
|
if (!command.Command.IsEmpty)
|
||||||
cmd.ShortCommand.ExtractText(),
|
AllCommands.TryAdd(command.Command.ToString(), command);
|
||||||
cmd.Alias.ExtractText(),
|
|
||||||
cmd.ShortAlias.ExtractText(),
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var command in commandNames)
|
if (!command.ShortCommand.IsEmpty)
|
||||||
AllCommands.Add(command);
|
AllCommands.TryAdd(command.ShortCommand.ToString(), command);
|
||||||
|
|
||||||
|
if (!command.Alias.IsEmpty)
|
||||||
|
AllCommands.TryAdd(command.Alias.ToString(), command);
|
||||||
|
|
||||||
|
if (!command.ShortAlias.IsEmpty)
|
||||||
|
AllCommands.TryAdd(command.ShortAlias.ToString(), command);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddBacklog(string message)
|
private void AddBacklog(string message)
|
||||||
@@ -736,7 +735,7 @@ public sealed class ChatLogWindow : Window
|
|||||||
if (!channel.IsValid())
|
if (!channel.IsValid())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var name = Sheets.LogFilterSheet.FirstOrNull(row => row.LogKind == (byte) channel.ToChatType())?.Name.ExtractText() ?? channel.ToChatType().Name();
|
var name = Sheets.LogFilterSheet.FirstOrNull(row => row.LogKind == (byte) channel.ToChatType())?.Name.ToString() ?? channel.ToChatType().Name();
|
||||||
if (channel.IsLinkshell())
|
if (channel.IsLinkshell())
|
||||||
{
|
{
|
||||||
var lsName = Plugin.Functions.Chat.GetLinkshellName(channel.LinkshellIndex());
|
var lsName = Plugin.Functions.Chat.GetLinkshellName(channel.LinkshellIndex());
|
||||||
@@ -933,13 +932,19 @@ public sealed class ChatLogWindow : Window
|
|||||||
AddBacklog(trimmed);
|
AddBacklog(trimmed);
|
||||||
InputBacklogIdx = -1;
|
InputBacklogIdx = -1;
|
||||||
|
|
||||||
|
if (HasTranslationCommand(trimmed))
|
||||||
|
{
|
||||||
|
activeTab.CurrentChannel.ResetTempChannel();
|
||||||
|
Chat = string.Empty;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (TellSpecial)
|
if (TellSpecial)
|
||||||
{
|
{
|
||||||
var tellBytes = Encoding.UTF8.GetBytes(trimmed);
|
var tellBytes = Encoding.UTF8.GetBytes(trimmed);
|
||||||
AutoTranslate.ReplaceWithPayload(ref tellBytes);
|
AutoTranslate.ReplaceWithPayload(ref tellBytes);
|
||||||
|
|
||||||
Plugin.Functions.Chat.SendTellUsingCommandInner(tellBytes);
|
Plugin.Functions.Chat.SendTellUsingCommandInner(tellBytes);
|
||||||
|
|
||||||
TellSpecial = false;
|
TellSpecial = false;
|
||||||
|
|
||||||
activeTab.CurrentChannel.ResetTempChannel();
|
activeTab.CurrentChannel.ResetTempChannel();
|
||||||
@@ -1000,6 +1005,18 @@ public sealed class ChatLogWindow : Window
|
|||||||
Chat = string.Empty;
|
Chat = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool HasTranslationCommand(string trimmed)
|
||||||
|
{
|
||||||
|
var messageBytes = Encoding.UTF8.GetBytes(trimmed);
|
||||||
|
if (AutoTranslate.StartsWithCommand(ref messageBytes))
|
||||||
|
{
|
||||||
|
ChatBox.SendMessageUnsafe(messageBytes);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
internal void UserHide()
|
internal void UserHide()
|
||||||
{
|
{
|
||||||
CurrentHideState = HideState.User;
|
CurrentHideState = HideState.User;
|
||||||
@@ -1492,10 +1509,11 @@ public sealed class ChatLogWindow : Window
|
|||||||
var button = (i + 1) % 10;
|
var button = (i + 1) % 10;
|
||||||
var text = string.Format(Language.AutoTranslate_Completion_Key, button);
|
var text = string.Format(Language.AutoTranslate_Completion_Key, button);
|
||||||
var size = ImGui.CalcTextSize(text);
|
var size = ImGui.CalcTextSize(text);
|
||||||
|
|
||||||
ImGui.SameLine(ImGui.GetContentRegionAvail().X - size.X);
|
ImGui.SameLine(ImGui.GetContentRegionAvail().X - size.X);
|
||||||
ImGui.PushStyleColor(ImGuiCol.Text, *ImGui.GetStyleColorVec4(ImGuiCol.TextDisabled));
|
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int)ImGuiCol.TextDisabled]))
|
||||||
ImGui.TextUnformatted(text);
|
ImGui.TextUnformatted(text);
|
||||||
ImGui.PopStyleColor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!clicked)
|
if (!clicked)
|
||||||
@@ -1632,12 +1650,10 @@ public sealed class ChatLogWindow : Window
|
|||||||
if (text.StartsWith('/'))
|
if (text.StartsWith('/'))
|
||||||
{
|
{
|
||||||
var command = text.Split(' ')[0];
|
var command = text.Split(' ')[0];
|
||||||
var cmd = Sheets.TextCommandSheet.FirstOrNull(cmd =>
|
if (AllCommands.TryGetValue(command, out var textCommand))
|
||||||
cmd.Command.ExtractText() == command || cmd.Alias.ExtractText() == command ||
|
Plugin.CommandHelpWindow.UpdateContent(textCommand.Description);
|
||||||
cmd.ShortCommand.ExtractText() == command || cmd.ShortAlias.ExtractText() == command);
|
else if (Plugin.CommandManager.Commands.TryGetValue(command, out var info) && info.ShowInHelp)
|
||||||
|
Plugin.CommandHelpWindow.UpdateContent(info.HelpMessage);
|
||||||
if (cmd != null)
|
|
||||||
Plugin.CommandHelpWindow.UpdateContent(cmd.Value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.EventFlag != ImGuiInputTextFlags.CallbackHistory)
|
if (data.EventFlag != ImGuiInputTextFlags.CallbackHistory)
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ using Dalamud.Interface.Utility;
|
|||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
using Lumina.Excel.Sheets;
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
namespace ChatTwo.Ui;
|
namespace ChatTwo.Ui;
|
||||||
|
|
||||||
public class CommandHelpWindow : Window {
|
public class CommandHelpWindow : Window {
|
||||||
private ChatLogWindow LogWindow { get; }
|
private ChatLogWindow LogWindow { get; }
|
||||||
private TextCommand? Command { get; set; }
|
private ReadOnlySeString? CommandDescription { get; set; }
|
||||||
|
|
||||||
internal CommandHelpWindow(ChatLogWindow logWindow) : base($"command help##chat2-commandhelp")
|
internal CommandHelpWindow(ChatLogWindow logWindow) : base("command help##chat2-commandhelp")
|
||||||
{
|
{
|
||||||
LogWindow = logWindow;
|
LogWindow = logWindow;
|
||||||
|
|
||||||
@@ -24,9 +24,9 @@ public class CommandHelpWindow : Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sets IsOpen to true if it should be drawn
|
// Sets IsOpen to true if it should be drawn
|
||||||
public void UpdateContent(TextCommand command)
|
public void UpdateContent(ReadOnlySeString commandDesc)
|
||||||
{
|
{
|
||||||
Command = command;
|
CommandDescription = commandDesc;
|
||||||
|
|
||||||
var width = 350;
|
var width = 350;
|
||||||
var scaledWidth = width * ImGuiHelpers.GlobalScale;
|
var scaledWidth = width * ImGuiHelpers.GlobalScale;
|
||||||
@@ -56,9 +56,9 @@ public class CommandHelpWindow : Window {
|
|||||||
|
|
||||||
public override void Draw()
|
public override void Draw()
|
||||||
{
|
{
|
||||||
if (Command == null)
|
if (CommandDescription == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
LogWindow.DrawChunks(ChunkUtil.ToChunks(Command.Value.Description.ToDalamudString(), ChunkSource.None, null).ToList());
|
LogWindow.DrawChunks(ChunkUtil.ToChunks(CommandDescription.Value.ToDalamudString(), ChunkSource.None, null).ToList());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ internal sealed class About : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool changed)
|
public void Draw(bool changed)
|
||||||
{
|
{
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
ImGui.TextUnformatted(string.Format(Language.Options_About_Opening, Plugin.PluginName));
|
ImGui.TextUnformatted(string.Format(Language.Options_About_Opening, Plugin.PluginName));
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ internal sealed class Changelog : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool changed)
|
public void Draw(bool changed)
|
||||||
{
|
{
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
ImGui.TextUnformatted(Language.Options_Warning_NotImplemented);
|
ImGui.TextUnformatted(Language.Options_Warning_NotImplemented);
|
||||||
ImGuiUtil.OptionCheckbox(ref Mutable.PrintChangelog, Language.Options_PrintChangelog_Name, Language.Options_PrintChangelog_Description);
|
ImGuiUtil.OptionCheckbox(ref Mutable.PrintChangelog, Language.Options_PrintChangelog_Name, Language.Options_PrintChangelog_Description);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ internal sealed class ChatLog : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool changed)
|
public void Draw(bool changed)
|
||||||
{
|
{
|
||||||
using (ImGuiUtil.TextWrapPos())
|
using (ImRaii.TextWrapPos(0.0f))
|
||||||
{
|
{
|
||||||
ImGuiUtil.OptionCheckbox(ref Mutable.KeepInputFocus, Language.Options_KeepInputFocus_Name, Language.Options_KeepInputFocus_Description);
|
ImGuiUtil.OptionCheckbox(ref Mutable.KeepInputFocus, Language.Options_KeepInputFocus_Name, Language.Options_KeepInputFocus_Description);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ internal sealed class Database : ISettingsTab
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
using var treeNode = ImRaii.TreeNode(Language.Options_Database_Advanced);
|
using var treeNode = ImRaii.TreeNode(Language.Options_Database_Advanced);
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
ImGuiUtil.WarningText(Language.Options_Database_Advanced_Warning);
|
ImGuiUtil.WarningText(Language.Options_Database_Advanced_Warning);
|
||||||
if (ImGuiUtil.CtrlShiftButton("Perform maintenance", "Ctrl+Shift: MessageManager.Store.PerformMaintenance()"))
|
if (ImGuiUtil.CtrlShiftButton("Perform maintenance", "Ctrl+Shift: MessageManager.Store.PerformMaintenance()"))
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ internal sealed class Display : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool changed)
|
public void Draw(bool changed)
|
||||||
{
|
{
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
ImGuiUtil.OptionCheckbox(ref Mutable.HideChat, Language.Options_HideChat_Name, Language.Options_HideChat_Description);
|
ImGuiUtil.OptionCheckbox(ref Mutable.HideChat, Language.Options_HideChat_Name, Language.Options_HideChat_Description);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ internal sealed class Emote : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool changed)
|
public void Draw(bool changed)
|
||||||
{
|
{
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
ImGuiUtil.OptionCheckbox(ref Mutable.ShowEmotes, Language.Options_ShowEmotes_Name, Language.Options_ShowEmotes_Desc);
|
ImGuiUtil.OptionCheckbox(ref Mutable.ShowEmotes, Language.Options_ShowEmotes_Name, Language.Options_ShowEmotes_Desc);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using ChatTwo.Util;
|
|||||||
using Dalamud;
|
using Dalamud;
|
||||||
using Dalamud.Interface.FontIdentifier;
|
using Dalamud.Interface.FontIdentifier;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
namespace ChatTwo.Ui.SettingsTabs;
|
namespace ChatTwo.Ui.SettingsTabs;
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ public class Fonts : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool _)
|
public void Draw(bool _)
|
||||||
{
|
{
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
ImGui.Checkbox(Language.Options_FontsEnabled, ref Mutable.FontsEnabled);
|
ImGui.Checkbox(Language.Options_FontsEnabled, ref Mutable.FontsEnabled);
|
||||||
ImGui.Spacing();
|
ImGui.Spacing();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using ChatTwo.Resources;
|
using ChatTwo.Resources;
|
||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using Dalamud.Bindings.ImGui;
|
using Dalamud.Bindings.ImGui;
|
||||||
|
using Dalamud.Interface.Utility.Raii;
|
||||||
|
|
||||||
namespace ChatTwo.Ui.SettingsTabs;
|
namespace ChatTwo.Ui.SettingsTabs;
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ internal sealed class Preview : ISettingsTab
|
|||||||
|
|
||||||
public void Draw(bool changed)
|
public void Draw(bool changed)
|
||||||
{
|
{
|
||||||
using var wrap = ImGuiUtil.TextWrapPos();
|
using var wrap = ImRaii.TextWrapPos(0.0f);
|
||||||
|
|
||||||
using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Preview_Name, Mutable.PreviewPosition.Name()))
|
using (var combo = ImGuiUtil.BeginComboVertical(Language.Options_Preview_Name, Mutable.PreviewPosition.Name()))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ internal sealed class Webinterface(Plugin plugin, Configuration mutable) : ISett
|
|||||||
clicked |= ImGuiUtil.IconButton(FontAwesomeIcon.ExternalLinkAlt, "urlOpen");
|
clicked |= ImGuiUtil.IconButton(FontAwesomeIcon.ExternalLinkAlt, "urlOpen");
|
||||||
|
|
||||||
if (clicked)
|
if (clicked)
|
||||||
WrapperUtil.TryOpenURI(uri);
|
WrapperUtil.TryOpenUri(uri);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,13 +3,12 @@ using System.Globalization;
|
|||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
|
||||||
using Dalamud.Utility;
|
using Dalamud.Utility;
|
||||||
using Lumina.Excel;
|
using Lumina.Excel;
|
||||||
using Lumina.Text.Payloads;
|
using Lumina.Text.Payloads;
|
||||||
using Lumina.Text.ReadOnly;
|
using Lumina.Text.ReadOnly;
|
||||||
using Pidgin;
|
using Pidgin;
|
||||||
|
|
||||||
using static Pidgin.Parser;
|
using static Pidgin.Parser;
|
||||||
using static Pidgin.Parser<char>;
|
using static Pidgin.Parser<char>;
|
||||||
|
|
||||||
@@ -157,6 +156,9 @@ internal static class AutoTranslate
|
|||||||
}
|
}
|
||||||
else if (lookup is not "@")
|
else if (lookup is not "@")
|
||||||
{
|
{
|
||||||
|
if (row.Text.IsEmpty)
|
||||||
|
continue;
|
||||||
|
|
||||||
list.Add(new AutoTranslateEntry(row.Group, row.RowId, row.Text.ToString(), row.GroupTitle.ToString()));
|
list.Add(new AutoTranslateEntry(row.Group, row.RowId, row.Text.ToString(), row.GroupTitle.ToString()));
|
||||||
|
|
||||||
if (shouldAdd)
|
if (shouldAdd)
|
||||||
@@ -242,9 +244,7 @@ internal static class AutoTranslate
|
|||||||
var parts = tag[4..^1].Split(',', 2);
|
var parts = tag[4..^1].Split(',', 2);
|
||||||
if (parts.Length == 2 && uint.TryParse(parts[0], out var group) && uint.TryParse(parts[1], out var key))
|
if (parts.Length == 2 && uint.TryParse(parts[0], out var group) && uint.TryParse(parts[1], out var key))
|
||||||
{
|
{
|
||||||
var payload = ValidEntries.Contains((group, key))
|
var payload = ValidEntries.Contains((group, key)) ? CreateFixedTranslation(group, key) : [];
|
||||||
? new AutoTranslatePayload(group, key).Encode()
|
|
||||||
: [];
|
|
||||||
|
|
||||||
var oldBytes = bytes.ToArray();
|
var oldBytes = bytes.ToArray();
|
||||||
var lengthDiff = payload.Length - (i - start);
|
var lengthDiff = payload.Length - (i - start);
|
||||||
@@ -263,56 +263,83 @@ internal static class AutoTranslate
|
|||||||
start = i;
|
start = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool StartsWithCommand(ref byte[] bytes)
|
||||||
|
{
|
||||||
|
var search = "<at:"u8;
|
||||||
|
if (bytes.Length <= search.Length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// populate the list of valid entries
|
||||||
|
if (ValidEntries.Count == 0)
|
||||||
|
AllEntries();
|
||||||
|
|
||||||
|
for (var i = 0; i < search.Length; i++)
|
||||||
|
{
|
||||||
|
if (bytes[i] != search[i])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < bytes.Length; i++)
|
||||||
|
{
|
||||||
|
if (bytes[i] != '>')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var tag = Encoding.UTF8.GetString(bytes[..(i + 1)]);
|
||||||
|
var parts = tag[4..^1].Split(',', 2);
|
||||||
|
if (parts.Length == 2 && uint.TryParse(parts[0], out var group) && uint.TryParse(parts[1], out var key))
|
||||||
|
{
|
||||||
|
if (!ValidEntries.Contains((group, key)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var evaluated = Plugin.Evaluator.Evaluate(new ReadOnlySeString(CreateFixedTranslation(group, key))).ToString();
|
||||||
|
if (!evaluated.StartsWith('/'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
bytes = Encoding.UTF8.GetBytes(evaluated);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] CreateFixedTranslation(uint group, uint key)
|
||||||
|
{
|
||||||
|
using var rssb = new RentedSeStringBuilder();
|
||||||
|
return rssb.Builder
|
||||||
|
.BeginMacro(MacroCode.Fixed)
|
||||||
|
.AppendUIntExpression(group - 1)
|
||||||
|
.AppendUIntExpression(key)
|
||||||
|
.EndMacro()
|
||||||
|
.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal interface ISelectorPart { }
|
internal interface ISelectorPart { }
|
||||||
|
|
||||||
internal class SingleRow : ISelectorPart
|
internal class SingleRow(uint row) : ISelectorPart
|
||||||
{
|
{
|
||||||
public uint Row { get; }
|
public uint Row { get; } = row;
|
||||||
|
|
||||||
public SingleRow(uint row)
|
|
||||||
{
|
|
||||||
Row = row;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class IndexRange : ISelectorPart
|
internal class IndexRange(uint start, uint end) : ISelectorPart
|
||||||
{
|
{
|
||||||
public uint Start { get; }
|
public uint Start { get; } = start;
|
||||||
public uint End { get; }
|
public uint End { get; } = end;
|
||||||
|
|
||||||
public IndexRange(uint start, uint end)
|
|
||||||
{
|
|
||||||
Start = start;
|
|
||||||
End = end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class NounMarker : ISelectorPart { }
|
internal class NounMarker : ISelectorPart { }
|
||||||
|
|
||||||
internal class ColumnSpecifier : ISelectorPart
|
internal class ColumnSpecifier(uint column) : ISelectorPart
|
||||||
{
|
{
|
||||||
public uint Column { get; }
|
public uint Column { get; } = column;
|
||||||
|
|
||||||
public ColumnSpecifier(uint column)
|
|
||||||
{
|
|
||||||
Column = column;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class AutoTranslateEntry
|
internal class AutoTranslateEntry(uint group, uint row, string str, string title)
|
||||||
{
|
{
|
||||||
internal uint Group { get; }
|
internal uint Group { get; } = group;
|
||||||
internal uint Row { get; }
|
internal uint Row { get; } = row;
|
||||||
internal string Text { get; }
|
internal string Text { get; } = str;
|
||||||
internal string Title { get; }
|
internal string Title { get; } = title;
|
||||||
|
|
||||||
public AutoTranslateEntry(uint group, uint row, string str, string title)
|
|
||||||
{
|
|
||||||
Group = group;
|
|
||||||
Row = row;
|
|
||||||
Text = str;
|
|
||||||
Title = title;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+277
-12
@@ -1,8 +1,11 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
using ChatTwo.Code;
|
using ChatTwo.Code;
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Lumina.Text.Expressions;
|
||||||
using Lumina.Text.Payloads;
|
using Lumina.Text.Payloads;
|
||||||
|
using Lumina.Text.ReadOnly;
|
||||||
|
|
||||||
using PayloadType = Dalamud.Game.Text.SeStringHandling.PayloadType;
|
using PayloadType = Dalamud.Game.Text.SeStringHandling.PayloadType;
|
||||||
|
|
||||||
@@ -10,6 +13,244 @@ namespace ChatTwo.Util;
|
|||||||
|
|
||||||
internal static class ChunkUtil
|
internal static class ChunkUtil
|
||||||
{
|
{
|
||||||
|
// internal static IEnumerable<Chunk> ToChunks(ReadOnlySeString msg, ChunkSource source, ChatType? defaultColour)
|
||||||
|
// {
|
||||||
|
// var chunks = new List<Chunk>();
|
||||||
|
//
|
||||||
|
// var italic = false;
|
||||||
|
// var foreground = new Stack<uint>();
|
||||||
|
// var glow = new Stack<uint>();
|
||||||
|
// Payload? link = null;
|
||||||
|
//
|
||||||
|
// void Append(string text)
|
||||||
|
// {
|
||||||
|
// chunks.Add(new TextChunk(source, link, text)
|
||||||
|
// {
|
||||||
|
// FallbackColour = defaultColour,
|
||||||
|
// Foreground = foreground.Count > 0 ? foreground.Peek() : null,
|
||||||
|
// Glow = glow.Count > 0 ? glow.Peek() : null,
|
||||||
|
// Italic = italic,
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// foreach (var payload in msg)
|
||||||
|
// {
|
||||||
|
// if (payload.Type == ReadOnlySePayloadType.Text)
|
||||||
|
// {
|
||||||
|
// // We don't want to parse any null string
|
||||||
|
// var str = payload.ToString();
|
||||||
|
// var nulIndex = str.IndexOf('\0');
|
||||||
|
// if (nulIndex > 0)
|
||||||
|
// str = str[..nulIndex];
|
||||||
|
// if (string.IsNullOrEmpty(str))
|
||||||
|
// continue;
|
||||||
|
//
|
||||||
|
// Append(str);
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// switch (payload.MacroCode)
|
||||||
|
// {
|
||||||
|
// case MacroCode.Italic:
|
||||||
|
// var newStatus = payload.TryGetExpression(out var expression) && expression.TryGetUInt(out var value) && value == 1;
|
||||||
|
// italic = newStatus;
|
||||||
|
// break;
|
||||||
|
// case MacroCode.Color:
|
||||||
|
// if (payload.TryGetExpression(out var eColor))
|
||||||
|
// {
|
||||||
|
// if (eColor.TryGetPlaceholderExpression(out var ph) && ph == (int)ExpressionType.StackColor)
|
||||||
|
// {
|
||||||
|
// if (foreground.Count > 0)
|
||||||
|
// foreground.Pop();
|
||||||
|
// }
|
||||||
|
// else if (TryResolveUInt(eColor, out var eColorVal))
|
||||||
|
// {
|
||||||
|
// var color = ColourUtil.ArgbToRgba(eColorVal);
|
||||||
|
//
|
||||||
|
// if (color > 0)
|
||||||
|
// foreground.Push(color);
|
||||||
|
// else if (foreground.Count > 0) // Push the previous color as we don't want invisible text
|
||||||
|
// foreground.Push(foreground.Peek());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MacroCode.EdgeColor:
|
||||||
|
// if (payload.TryGetExpression(out eColor))
|
||||||
|
// {
|
||||||
|
// if (eColor.TryGetPlaceholderExpression(out var ph) && ph == (int)ExpressionType.StackColor)
|
||||||
|
// {
|
||||||
|
// if (glow.Count > 0)
|
||||||
|
// glow.Pop();
|
||||||
|
// }
|
||||||
|
// else if (TryResolveUInt(eColor, out var eColorVal))
|
||||||
|
// {
|
||||||
|
// glow.Push(ColourUtil.ArgbToRgba(eColorVal));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MacroCode.ColorType:
|
||||||
|
// if (!payload.TryGetExpression(out var eColorType) || !eColorType.TryGetUInt(out var eColorTypeVal))
|
||||||
|
// {
|
||||||
|
// if (foreground.Count > 0)
|
||||||
|
// foreground.Pop();
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (eColorTypeVal == 0)
|
||||||
|
// {
|
||||||
|
// if (foreground.Count > 0)
|
||||||
|
// foreground.Pop();
|
||||||
|
// }
|
||||||
|
// else if (Sheets.UIColorSheet.TryGetRow(eColorTypeVal, out var row))
|
||||||
|
// {
|
||||||
|
// foreground.Push(row.Dark);
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MacroCode.EdgeColorType:
|
||||||
|
// if (!payload.TryGetExpression(out var eEdgeColor) || !eEdgeColor.TryGetUInt(out var eEdgeColorVal))
|
||||||
|
// {
|
||||||
|
// if (glow.Count > 0)
|
||||||
|
// glow.Pop();
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (eEdgeColorVal == 0)
|
||||||
|
// {
|
||||||
|
// if (glow.Count > 0)
|
||||||
|
// glow.Pop();
|
||||||
|
// }
|
||||||
|
// else if (Sheets.UIColorSheet.TryGetRow(eEdgeColorVal, out var row))
|
||||||
|
// {
|
||||||
|
// glow.Push(row.Dark);
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MacroCode.Fixed:
|
||||||
|
// if (!payload.TryGetExpression(out var expr1, out var expr2))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (expr1.TryGetUInt(out var group) && expr2.TryGetUInt(out var key))
|
||||||
|
// {
|
||||||
|
// chunks.Add(new IconChunk(source, null, BitmapFontIcon.AutoTranslateBegin));
|
||||||
|
// using var rssb = new RentedSeStringBuilder();
|
||||||
|
// var translatePayload = rssb.Builder
|
||||||
|
// .BeginMacro(MacroCode.Fixed)
|
||||||
|
// .AppendUIntExpression(group - 1)
|
||||||
|
// .AppendUIntExpression(key)
|
||||||
|
// .EndMacro()
|
||||||
|
// .ToReadOnlySeString();
|
||||||
|
//
|
||||||
|
// Append(Plugin.Evaluator.Evaluate(translatePayload).ToString());
|
||||||
|
// chunks.Add(new IconChunk(source, null, BitmapFontIcon.AutoTranslateEnd));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MacroCode.Icon:
|
||||||
|
// if (payload.TryGetExpression(out var eIcon) && TryResolveInt(eIcon, out var iconVal))
|
||||||
|
// chunks.Add(new IconChunk(source, link, (BitmapFontIcon)iconVal));
|
||||||
|
// break;
|
||||||
|
// case MacroCode.Link:
|
||||||
|
// if (!payload.TryGetExpression(
|
||||||
|
// out var linkTypeExpr1,
|
||||||
|
// out var uintExpr2,
|
||||||
|
// out var intExpr3,
|
||||||
|
// out var intExpr4,
|
||||||
|
// out var strExpr5))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!linkTypeExpr1.TryGetUInt(out var linkType))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// switch ((LinkMacroPayloadType)linkType)
|
||||||
|
// {
|
||||||
|
// case LinkMacroPayloadType.Terminator:
|
||||||
|
// link = null;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.MapPosition:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var ids))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!intExpr3.TryGetInt(out var rawX))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!intExpr4.TryGetInt(out var rawY))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// var mapId = ids & 0xFF;
|
||||||
|
// var territoryId = (ids >> 16) & 0xFF;
|
||||||
|
// break;
|
||||||
|
// case (LinkMacroPayloadType)Payload.EmbeddedInfoType.DalamudLink - 1:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var commandId))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!intExpr3.TryGetInt(out var extra1))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!intExpr4.TryGetInt(out var extra2))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!strExpr5.TryGetString(out var extraStr))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.Quest:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var questId))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.Status:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var statusId))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.Item:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var itemId))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.Character:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var flags))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// if (!intExpr3.TryGetUInt(out var worldId))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.PartyFinder:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var listingId))
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // intExpr3 is unused
|
||||||
|
//
|
||||||
|
// if (!intExpr4.TryGetUInt(out worldId))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.PartyFinderNotification:
|
||||||
|
// // no expr used
|
||||||
|
// break;
|
||||||
|
// case LinkMacroPayloadType.Achievement:
|
||||||
|
// if (!uintExpr2.TryGetUInt(out var achievementId))
|
||||||
|
// break;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// case MacroCode.NonBreakingSpace:
|
||||||
|
// Append(" ");
|
||||||
|
// break;
|
||||||
|
// case PayloadType.Unknown:
|
||||||
|
// var rawPayload = (RawPayload)payload;
|
||||||
|
// else if (rawPayload.Data.Length > 1 && rawPayload.Data[1] == 0x14)
|
||||||
|
// {
|
||||||
|
// if (glow.Count > 0)
|
||||||
|
// {
|
||||||
|
// glow.Pop();
|
||||||
|
// }
|
||||||
|
// else if (rawPayload.Data.Length > 6 && rawPayload.Data[2] == 0x05 && rawPayload.Data[3] == 0xF6)
|
||||||
|
// {
|
||||||
|
// var (r, g, b) = (rawPayload.Data[4], rawPayload.Data[5], rawPayload.Data[6]);
|
||||||
|
// glow.Push(ColourUtil.ComponentsToRgba(r, g, b));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return chunks;
|
||||||
|
// }
|
||||||
|
|
||||||
internal static IEnumerable<Chunk> ToChunks(SeString msg, ChunkSource source, ChatType? defaultColour)
|
internal static IEnumerable<Chunk> ToChunks(SeString msg, ChunkSource source, ChatType? defaultColour)
|
||||||
{
|
{
|
||||||
var chunks = new List<Chunk>();
|
var chunks = new List<Chunk>();
|
||||||
@@ -176,22 +417,46 @@ internal static class ChunkUtil
|
|||||||
return BitConverter.ToUInt32(numArray, 0);
|
return BitConverter.ToUInt32(numArray, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static unsafe void PrintMemoryArea(nint address, int length)
|
private static bool TryResolveUInt(in ReadOnlySeExpressionSpan expression, out uint value)
|
||||||
{
|
{
|
||||||
var ptr = (byte*)address;
|
if (expression.TryGetUInt(out value))
|
||||||
var str = new StringBuilder("\n");
|
return true;
|
||||||
for(var i = 0; i < length; i++)
|
|
||||||
|
if (expression.TryGetParameterExpression(out var exprType, out var operand1))
|
||||||
{
|
{
|
||||||
str.Append($"{ptr![i]:X02}");
|
if (!TryResolveUInt(operand1, out var paramIndex))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (i == 0)
|
if (paramIndex == 0)
|
||||||
continue;
|
return false;
|
||||||
|
|
||||||
if ((i+1) % 16 == 0)
|
paramIndex--;
|
||||||
str.Append('\n');
|
if ((ExpressionType)exprType == ExpressionType.GlobalNumber)
|
||||||
else if ((i+1) % 4 == 0)
|
{
|
||||||
str.Append(' ');
|
value = (uint) GlobalParametersCache.GetValue((int)paramIndex);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
Plugin.Log.Information(str.ToString());
|
// return (ExpressionType)exprType switch
|
||||||
|
// {
|
||||||
|
// // ExpressionType.LocalNumber => context.TryGetLNum((int)paramIndex, out value), // lnum
|
||||||
|
// ExpressionType.GlobalNumber => (uint) GlobalParametersCache.GetValue((int)paramIndex), // gnum
|
||||||
|
// _ => false, // gstr, lstr
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static bool TryResolveInt(in ReadOnlySeExpressionSpan expression, out int value)
|
||||||
|
{
|
||||||
|
if (TryResolveUInt(expression, out var u32))
|
||||||
|
{
|
||||||
|
value = (int)u32;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = 0;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ using System.Numerics;
|
|||||||
namespace ChatTwo.Util;
|
namespace ChatTwo.Util;
|
||||||
|
|
||||||
internal static class ColourUtil {
|
internal static class ColourUtil {
|
||||||
internal static (byte r, byte g, byte b, byte a) RgbaToComponents(uint rgba)
|
private static (byte r, byte g, byte b, byte a) RgbaToComponents(uint rgba)
|
||||||
{
|
{
|
||||||
var r = (byte) ((rgba & 0xFF000000) >> 24);
|
var r = (byte) ((rgba & 0xFF000000) >> 24);
|
||||||
var g = (byte) ((rgba & 0xFF0000) >> 16);
|
var g = (byte) ((rgba & 0xFF0000) >> 16);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public static class DateWidget
|
|||||||
private static float LongestMonthWidth;
|
private static float LongestMonthWidth;
|
||||||
private static readonly float[] MonthWidths = new float[12];
|
private static readonly float[] MonthWidths = new float[12];
|
||||||
|
|
||||||
private static uint LastOpenComboID;
|
private static uint LastOpenComboId;
|
||||||
|
|
||||||
public static bool Validate(DateTime minimal, ref DateTime currentMin, ref DateTime currentMax)
|
public static bool Validate(DateTime minimal, ref DateTime currentMin, ref DateTime currentMax)
|
||||||
{
|
{
|
||||||
@@ -109,9 +109,9 @@ public static class DateWidget
|
|||||||
// reset date when user right-clicks the date chooser header when the dialog is open
|
// reset date when user right-clicks the date chooser header when the dialog is open
|
||||||
dateOut = DateTime.Now;
|
dateOut = DateTime.Now;
|
||||||
}
|
}
|
||||||
else if (LastOpenComboID != id)
|
else if (LastOpenComboId != id)
|
||||||
{
|
{
|
||||||
LastOpenComboID = id;
|
LastOpenComboId = id;
|
||||||
if (dateOut.Year == 1)
|
if (dateOut.Year == 1)
|
||||||
dateOut = DateTime.Now;
|
dateOut = DateTime.Now;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
public class ColorPayload
|
public class ColorPayload
|
||||||
{
|
{
|
||||||
private const byte START_BYTE = 2;
|
private const byte StartByte = 2;
|
||||||
|
|
||||||
public bool Enabled;
|
public bool Enabled;
|
||||||
public uint Color;
|
public uint Color;
|
||||||
@@ -11,7 +11,7 @@ public class ColorPayload
|
|||||||
public static ColorPayload? From(byte[] data)
|
public static ColorPayload? From(byte[] data)
|
||||||
{
|
{
|
||||||
using var stream = new MemoryStream(data);
|
using var stream = new MemoryStream(data);
|
||||||
if (stream.ReadByte() != START_BYTE || stream.ReadByte() != 0x13)
|
if (stream.ReadByte() != StartByte || stream.ReadByte() != 0x13)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
stream.ReadByte(); // skip the length byte;
|
stream.ReadByte(); // skip the length byte;
|
||||||
|
|||||||
+23
-115
@@ -183,13 +183,15 @@ internal static class ImGuiUtil
|
|||||||
if (id != null)
|
if (id != null)
|
||||||
label += $"##{id}";
|
label += $"##{id}";
|
||||||
|
|
||||||
Plugin.FontManager.FontAwesome.Push();
|
bool ret;
|
||||||
var size = new Vector2(0, 0);
|
using (Plugin.FontManager.FontAwesome.Push())
|
||||||
|
{
|
||||||
|
var size = Vector2.Zero;
|
||||||
if (width > 0)
|
if (width > 0)
|
||||||
size.X = width - 2 * ImGui.GetStyle().CellPadding.X;
|
size.X = width - 2 * ImGui.GetStyle().CellPadding.X;
|
||||||
|
|
||||||
var ret = ImGui.Button(label, size);
|
ret = ImGui.Button(label, size);
|
||||||
Plugin.FontManager.FontAwesome.Pop();
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tooltip) && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
if (!string.IsNullOrEmpty(tooltip) && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
Tooltip(tooltip);
|
Tooltip(tooltip);
|
||||||
@@ -200,7 +202,7 @@ internal static class ImGuiUtil
|
|||||||
internal static bool OptionCheckbox(ref bool value, string label, string? description = null)
|
internal static bool OptionCheckbox(ref bool value, string label, string? description = null)
|
||||||
{
|
{
|
||||||
var ret = ImGui.Checkbox(label, ref value);
|
var ret = ImGui.Checkbox(label, ref value);
|
||||||
if (description != null)
|
if (!string.IsNullOrEmpty(description))
|
||||||
HelpText(description);
|
HelpText(description);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -208,26 +210,20 @@ internal static class ImGuiUtil
|
|||||||
|
|
||||||
internal static void HelpText(string text)
|
internal static void HelpText(string text)
|
||||||
{
|
{
|
||||||
var colour = ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled];
|
using (ImRaii.TextWrapPos(0.0f))
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.Text, ImGui.GetStyle().Colors[(int) ImGuiCol.TextDisabled]))
|
||||||
using (TextWrapPos())
|
|
||||||
using (ImRaii.PushColor(ImGuiCol.Text, colour))
|
|
||||||
{
|
|
||||||
ImGui.TextUnformatted(text);
|
ImGui.TextUnformatted(text);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal static void WarningText(string text, bool wrap = true)
|
internal static void WarningText(string text, bool wrap = true)
|
||||||
{
|
{
|
||||||
var style = StyleModel.GetConfiguredStyle() ?? StyleModel.GetFromCurrent();
|
var style = StyleModel.GetConfiguredStyle() ?? StyleModel.GetFromCurrent();
|
||||||
var dalamudOrange = style.BuiltInColors?.DalamudOrange;
|
var dalamudOrange = style.BuiltInColors?.DalamudOrange;
|
||||||
|
|
||||||
using (TextWrapPos(wrap))
|
using (ImRaii.TextWrapPos(wrap ? 0.0f : ImGui.GetFontSize() * 35.0f))
|
||||||
using (ImRaii.PushColor(ImGuiCol.Text, dalamudOrange ?? Vector4.Zero, dalamudOrange != null))
|
using (ImRaii.PushColor(ImGuiCol.Text, dalamudOrange ?? Vector4.Zero, dalamudOrange != null))
|
||||||
{
|
|
||||||
ImGui.TextUnformatted(text);
|
ImGui.TextUnformatted(text);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal static ImRaii.IEndObject BeginComboVertical(string label, string previewValue, ImGuiComboFlags flags = ImGuiComboFlags.None)
|
internal static ImRaii.IEndObject BeginComboVertical(string label, string previewValue, ImGuiComboFlags flags = ImGuiComboFlags.None)
|
||||||
{
|
{
|
||||||
@@ -267,10 +263,8 @@ internal static class ImGuiUtil
|
|||||||
{
|
{
|
||||||
using (ImRaii.Tooltip())
|
using (ImRaii.Tooltip())
|
||||||
using (ImRaii.TextWrapPos(ImGui.GetFontSize() * 35.0f))
|
using (ImRaii.TextWrapPos(ImGui.GetFontSize() * 35.0f))
|
||||||
{
|
|
||||||
ImGui.TextUnformatted(tooltip);
|
ImGui.TextUnformatted(tooltip);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static SingleFontChooserDialog? FontChooser(string label, SingleFontSpec font, bool checkbox, ref bool checkboxValue, Predicate<IFontFamilyId>? exclusion = null, string? preview = null)
|
public static SingleFontChooserDialog? FontChooser(string label, SingleFontSpec font, bool checkbox, ref bool checkboxValue, Predicate<IFontFamilyId>? exclusion = null, string? preview = null)
|
||||||
{
|
{
|
||||||
@@ -306,21 +300,19 @@ internal static class ImGuiUtil
|
|||||||
ImGui.TextUnformatted(label);
|
ImGui.TextUnformatted(label);
|
||||||
ImGui.SetNextItemWidth(-1);
|
ImGui.SetNextItemWidth(-1);
|
||||||
using var combo = ImRaii.Combo($"##{label}", $"{currentSize:###.##}pt");
|
using var combo = ImRaii.Combo($"##{label}", $"{currentSize:###.##}pt");
|
||||||
if (combo)
|
if (!combo.Success)
|
||||||
{
|
return;
|
||||||
|
|
||||||
foreach (var size in FontManager.AxisFontSizeList)
|
foreach (var size in FontManager.AxisFontSizeList)
|
||||||
if (ImGui.Selectable($"{size:###.##}pt", currentSize.Equals(size)))
|
if (ImGui.Selectable($"{size:###.##}pt", currentSize.Equals(size)))
|
||||||
currentSize = size;
|
currentSize = size;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static bool Button(string id, FontAwesomeIcon icon, bool disabled)
|
public static bool Button(string id, FontAwesomeIcon icon, bool disabled)
|
||||||
{
|
{
|
||||||
using (ImRaii.Disabled(disabled))
|
using (ImRaii.Disabled(disabled))
|
||||||
{
|
|
||||||
return ImGuiComponents.IconButton(id, icon);
|
return ImGuiComponents.IconButton(id, icon);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
internal static bool CtrlShiftButton(string label, string tooltip = "")
|
internal static bool CtrlShiftButton(string label, string tooltip = "")
|
||||||
{
|
{
|
||||||
@@ -330,30 +322,12 @@ internal static class ImGuiUtil
|
|||||||
using (ImRaii.Disabled(!ctrlShiftHeld))
|
using (ImRaii.Disabled(!ctrlShiftHeld))
|
||||||
ret = ImGui.Button(label) && ctrlShiftHeld;
|
ret = ImGui.Button(label) && ctrlShiftHeld;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tooltip) && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
if (tooltip.Length != 0 && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
||||||
Tooltip(tooltip);
|
Tooltip(tooltip);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool CtrlShiftButtonColored(string label, string tooltip = "")
|
|
||||||
{
|
|
||||||
var ctrlShiftHeld = ImGui.GetIO() is { KeyCtrl: true, KeyShift: true };
|
|
||||||
|
|
||||||
var colorNormal = new Vector4(0.780f, 0.245f, 0.245f, 1.0f);
|
|
||||||
var colorHovered = new Vector4(0.7f, 0.0f, 0.0f, 1.0f);
|
|
||||||
using (ImRaii.PushColor(ImGuiCol.Button, colorNormal))
|
|
||||||
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, colorHovered))
|
|
||||||
{
|
|
||||||
var ret = ImGui.Button(label) && ctrlShiftHeld;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(tooltip) && ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled))
|
|
||||||
Tooltip(tooltip);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static void KeybindInput(string id, ref ConfigKeyBind? keybind)
|
internal static void KeybindInput(string id, ref ConfigKeyBind? keybind)
|
||||||
{
|
{
|
||||||
var idUint = ImGui.GetID(id);
|
var idUint = ImGui.GetID(id);
|
||||||
@@ -394,19 +368,15 @@ internal static class ImGuiUtil
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var vk in Enum.GetValues(typeof(VirtualKey)).Cast<VirtualKey>())
|
foreach (var vk in Enum.GetValues<VirtualKey>())
|
||||||
{
|
{
|
||||||
if (vk is VirtualKey.NO_KEY or VirtualKey.CONTROL or VirtualKey.LCONTROL or VirtualKey.RCONTROL or VirtualKey.SHIFT or VirtualKey.LSHIFT or VirtualKey.RSHIFT or VirtualKey.MENU or VirtualKey.LMENU or VirtualKey.RMENU)
|
if (vk is VirtualKey.NO_KEY or VirtualKey.CONTROL or VirtualKey.LCONTROL or VirtualKey.RCONTROL or VirtualKey.SHIFT or VirtualKey.LSHIFT or VirtualKey.RSHIFT or VirtualKey.MENU or VirtualKey.LMENU or VirtualKey.RMENU)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!TryToImGui(vk, out var imKey) || !ImGui.IsKeyPressed(imKey))
|
if (!vk.TryToImGui(out var imKey) || !ImGui.IsKeyPressed(imKey))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
keybind = new ConfigKeyBind
|
keybind = new ConfigKeyBind { Modifier = currentMods, Key = vk };
|
||||||
{
|
|
||||||
Modifier = currentMods,
|
|
||||||
Key = vk
|
|
||||||
};
|
|
||||||
ImGui.GetStateStorage().SetBool(idUint, false);
|
ImGui.GetStateStorage().SetBool(idUint, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -442,6 +412,12 @@ internal static class ImGuiUtil
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void WrappedTextWithColor(Vector4 color, string text)
|
||||||
|
{
|
||||||
|
using (ImRaii.PushColor(ImGuiCol.Text, color))
|
||||||
|
ImGui.TextWrapped(text);
|
||||||
|
}
|
||||||
|
|
||||||
public static void CenterText(string text, float indent = 0.0f)
|
public static void CenterText(string text, float indent = 0.0f)
|
||||||
{
|
{
|
||||||
indent *= ImGuiHelpers.GlobalScale;
|
indent *= ImGuiHelpers.GlobalScale;
|
||||||
@@ -566,63 +542,6 @@ internal static class ImGuiUtil
|
|||||||
return result != 0 || key == VirtualKey.NO_KEY;
|
return result != 0 || key == VirtualKey.NO_KEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct EndUnconditionally(Action endAction, bool success) : ImRaii.IEndObject
|
|
||||||
{
|
|
||||||
public bool Success { get; } = success;
|
|
||||||
|
|
||||||
private bool Disposed { get; set; } = false;
|
|
||||||
private Action EndAction { get; } = endAction;
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!Disposed)
|
|
||||||
{
|
|
||||||
EndAction();
|
|
||||||
Disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use end-function only on success.
|
|
||||||
private struct EndConditionally(Action endAction, bool success) : ImRaii.IEndObject
|
|
||||||
{
|
|
||||||
public bool Success { get; } = success;
|
|
||||||
|
|
||||||
private bool Disposed { get; set; } = false;
|
|
||||||
private Action EndAction { get; } = endAction;
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (Disposed)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Success)
|
|
||||||
EndAction();
|
|
||||||
|
|
||||||
Disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImRaii.IEndObject TextWrapPos()
|
|
||||||
{
|
|
||||||
ImGui.PushTextWrapPos();
|
|
||||||
return new EndUnconditionally(ImGui.PopTextWrapPos, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImRaii.IEndObject TextWrapPos(bool condition)
|
|
||||||
{
|
|
||||||
if (!condition)
|
|
||||||
return new EndUnconditionally(Nop, false);
|
|
||||||
|
|
||||||
ImGui.PushTextWrapPos();
|
|
||||||
return new EndUnconditionally(ImGui.PopTextWrapPos, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImRaii.IEndObject Menu(string label)
|
|
||||||
{
|
|
||||||
return new EndConditionally(ImGui.EndMenu, ImGui.BeginMenu(label));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void ChannelSelector(string headerText, Dictionary<ChatType, ChatSource> chatCodes)
|
public static void ChannelSelector(string headerText, Dictionary<ChatType, ChatSource> chatCodes)
|
||||||
{
|
{
|
||||||
using var channelNode = ImRaii.TreeNode(headerText);
|
using var channelNode = ImRaii.TreeNode(headerText);
|
||||||
@@ -696,15 +615,4 @@ internal static class ImGuiUtil
|
|||||||
extraChatChannels.Remove(id);
|
extraChatChannels.Remove(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void WrappedTextWithColor(Vector4 color, string text)
|
|
||||||
{
|
|
||||||
using (ImRaii.PushColor(ImGuiCol.Text, color))
|
|
||||||
{
|
|
||||||
ImGui.TextWrapped(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to avoid pops if condition is false for Push.
|
|
||||||
private static void Nop() { }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,13 +25,10 @@ public static class MathUtil
|
|||||||
SizeY = Y + Height;
|
SizeY = Y + Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle(Vector2 pos, Vector2 size)
|
public Rectangle(Vector2 pos, Vector2 size) : this((int) pos.X, (int) pos.Y, (int) size.X, (int) size.Y) { }
|
||||||
: this((int) pos.X, (int) pos.Y, (int) size.X, (int) size.Y) { }
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
=> $"X: {X} Y: {Y} Width: {Width} Height: {Height}";
|
||||||
return $"X: {X} Y: {Y} Width: {Width} Height: {Height}";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// From: https://stackoverflow.com/a/306379
|
// From: https://stackoverflow.com/a/306379
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace ChatTwo.Util;
|
||||||
|
|
||||||
|
public static class MemoryUtil
|
||||||
|
{
|
||||||
|
public static unsafe void PrintMemoryArea(nint address, int length)
|
||||||
|
{
|
||||||
|
var ptr = (byte*)address;
|
||||||
|
var str = new StringBuilder("\n");
|
||||||
|
for(var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
str.Append($"{ptr![i]:X02}");
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((i+1) % 16 == 0)
|
||||||
|
str.Append('\n');
|
||||||
|
else if ((i+1) % 4 == 0)
|
||||||
|
str.Append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin.Log.Information(str.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,18 +63,18 @@ internal class UriPayload(Uri uri) : Payload
|
|||||||
/// <exception cref="UriFormatException">
|
/// <exception cref="UriFormatException">
|
||||||
/// If the URI is invalid, or if the scheme is not supported.
|
/// If the URI is invalid, or if the scheme is not supported.
|
||||||
/// </exception>
|
/// </exception>
|
||||||
public static UriPayload ResolveURI(string rawURI)
|
public static UriPayload ResolveUri(string rawUri)
|
||||||
{
|
{
|
||||||
ArgumentNullException.ThrowIfNull(rawURI);
|
ArgumentNullException.ThrowIfNull(rawUri);
|
||||||
|
|
||||||
// Check for an expected scheme '://', if not add 'https://'
|
// Check for an expected scheme '://', if not add 'https://'
|
||||||
if (ExpectedSchemes.Any(scheme => rawURI.StartsWith($"{scheme}://")))
|
if (ExpectedSchemes.Any(scheme => rawUri.StartsWith($"{scheme}://")))
|
||||||
return new UriPayload(new Uri(rawURI));
|
return new UriPayload(new Uri(rawUri));
|
||||||
|
|
||||||
if (rawURI.Contains("://"))
|
if (rawUri.Contains("://"))
|
||||||
throw new UriFormatException($"Unsupported scheme in URL: {rawURI}");
|
throw new UriFormatException($"Unsupported scheme in URL: {rawUri}");
|
||||||
|
|
||||||
return new UriPayload(new Uri($"{DefaultScheme}://{rawURI}"));
|
return new UriPayload(new Uri($"{DefaultScheme}://{rawUri}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DecodeImpl(BinaryReader reader, long endOfStream)
|
protected override void DecodeImpl(BinaryReader reader, long endOfStream)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ internal static class TabsUtil
|
|||||||
var channels = new Dictionary<ChatType, ChatSource>();
|
var channels = new Dictionary<ChatType, ChatSource>();
|
||||||
foreach (var chatType in Enum.GetValues<ChatType>())
|
foreach (var chatType in Enum.GetValues<ChatType>())
|
||||||
channels[chatType] = ChatSourceExt.All;
|
channels[chatType] = ChatSourceExt.All;
|
||||||
|
|
||||||
return channels;
|
return channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ internal static class TabsUtil
|
|||||||
[ChatType.MessageBook] = ChatSourceExt.All,
|
[ChatType.MessageBook] = ChatSourceExt.All,
|
||||||
[ChatType.Alarm] = ChatSourceExt.All,
|
[ChatType.Alarm] = ChatSourceExt.All,
|
||||||
[ChatType.GlamourNotifications] = ChatSourceExt.All,
|
[ChatType.GlamourNotifications] = ChatSourceExt.All,
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
internal static Tab VanillaEvent => new()
|
internal static Tab VanillaEvent => new()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public static class Tokenizer
|
|||||||
new TokenDefinition(TokenType.Whitespace, "\\s", 1),
|
new TokenDefinition(TokenType.Whitespace, "\\s", 1),
|
||||||
new TokenDefinition(TokenType.Equals, "=", 1),
|
new TokenDefinition(TokenType.Equals, "=", 1),
|
||||||
new TokenDefinition(TokenType.OpenParenthesis, "\\(", 1),
|
new TokenDefinition(TokenType.OpenParenthesis, "\\(", 1),
|
||||||
new TokenDefinition(TokenType.UrlString, URLRegex, 1),
|
new TokenDefinition(TokenType.UrlString, UrlRegex, 1),
|
||||||
new TokenDefinition(TokenType.StringValue, "\\p{IsBasicLatin}", 2),
|
new TokenDefinition(TokenType.StringValue, "\\p{IsBasicLatin}", 2),
|
||||||
new TokenDefinition(TokenType.Leftover, ".", 3)
|
new TokenDefinition(TokenType.Leftover, ".", 3)
|
||||||
];
|
];
|
||||||
@@ -127,7 +127,7 @@ public static class Tokenizer
|
|||||||
private class TokenMatch
|
private class TokenMatch
|
||||||
{
|
{
|
||||||
public TokenType TokenType { get; set; }
|
public TokenType TokenType { get; set; }
|
||||||
public string Value { get; set; }
|
public required string Value { get; set; }
|
||||||
public int StartIndex { get; set; }
|
public int StartIndex { get; set; }
|
||||||
public int EndIndex { get; set; }
|
public int EndIndex { get; set; }
|
||||||
public int Precedence { get; set; }
|
public int Precedence { get; set; }
|
||||||
@@ -145,7 +145,7 @@ public static class Tokenizer
|
|||||||
/// It matches URLs with www. or https:// prefix, and also matches URLs
|
/// It matches URLs with www. or https:// prefix, and also matches URLs
|
||||||
/// without a prefix on specific TLDs.
|
/// without a prefix on specific TLDs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static Regex URLRegex = new(
|
private static readonly Regex UrlRegex = new(
|
||||||
@"(?<URL>((https?:\/\/|www\.)[a-z0-9-]+(\.[a-z0-9-]+)*|([a-z0-9-]+(\.[a-z0-9-]+)*\.(com|net|org|co|io|app)))(:[\d]{1,5})?(\/[^\s]*)?)",
|
@"(?<URL>((https?:\/\/|www\.)[a-z0-9-]+(\.[a-z0-9-]+)*|([a-z0-9-]+(\.[a-z0-9-]+)*\.(com|net|org|co|io|app)))(:[\d]{1,5})?(\/[^\s]*)?)",
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
|
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Runtime.CompilerServices;
|
using ChatTwo.Resources;
|
||||||
using ChatTwo.Resources;
|
|
||||||
using Dalamud.Interface.ImGuiNotification;
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
|
|
||||||
namespace ChatTwo.Util;
|
namespace ChatTwo.Util;
|
||||||
@@ -11,7 +10,7 @@ public static class WrapperUtil
|
|||||||
Plugin.Notification.AddNotification(new Notification { Content = content, Type = type, Minimized = minimized });
|
Plugin.Notification.AddNotification(new Notification { Content = content, Type = type, Minimized = minimized });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void TryOpenURI(Uri uri)
|
public static void TryOpenUri(Uri uri)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -24,21 +23,4 @@ public static class WrapperUtil
|
|||||||
AddNotification(Language.Context_OpenInBrowserError, NotificationType.Error);
|
AddNotification(Language.Context_OpenInBrowserError, NotificationType.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<(T Value, int Index)> WithIndex<T>(this IEnumerable<T> list)
|
|
||||||
=> list.Select((x, i) => (x, i));
|
|
||||||
|
|
||||||
/// <summary> Return the first object fulfilling the predicate or null for structs.</summary>
|
|
||||||
/// <param name="values"> The enumerable. </param>
|
|
||||||
/// <param name="predicate"> The predicate. </param>
|
|
||||||
/// <returns> The first object fulfilling the predicate, or a null-optional. </returns>
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
|
||||||
public static T? FirstOrNull<T>(this IEnumerable<T> values, Func<T, bool> predicate) where T : struct
|
|
||||||
{
|
|
||||||
foreach(var val in values)
|
|
||||||
if (predicate(val))
|
|
||||||
return val;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,9 @@
|
|||||||
"net10.0-windows7.0": {
|
"net10.0-windows7.0": {
|
||||||
"DalamudPackager": {
|
"DalamudPackager": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
"requested": "[14.0.1, )",
|
"requested": "[14.0.2, )",
|
||||||
"resolved": "14.0.1",
|
"resolved": "14.0.2",
|
||||||
"contentHash": "y0WWyUE6dhpGdolK3iKgwys05/nZaVf4ZPtIjpLhJBZvHxkkiE23zYRo7K7uqAgoK/QvK5cqF6l3VG5AbgC6KA=="
|
"contentHash": "dQJeq+8eyHzra4Cg5eZ/3LAeS3/UpvvLriYJGSncMK9LqJ7Q4B6jwcOsxo3PfxVd15xj+IzVFxkPqIBmPQu8/w=="
|
||||||
},
|
},
|
||||||
"DotNet.ReproducibleBuilds": {
|
"DotNet.ReproducibleBuilds": {
|
||||||
"type": "Direct",
|
"type": "Direct",
|
||||||
|
|||||||
Reference in New Issue
Block a user