diff --git a/ChatTwo/ChatTwo.csproj b/ChatTwo/ChatTwo.csproj index 875f50f..fcf5f9b 100755 --- a/ChatTwo/ChatTwo.csproj +++ b/ChatTwo/ChatTwo.csproj @@ -9,6 +9,8 @@ false true preview + true + full @@ -47,10 +49,10 @@ - + - + @@ -80,4 +82,4 @@ - \ No newline at end of file + diff --git a/ChatTwo/Configuration.cs b/ChatTwo/Configuration.cs index 41558e4..e9b8faa 100755 --- a/ChatTwo/Configuration.cs +++ b/ChatTwo/Configuration.cs @@ -34,6 +34,7 @@ internal class Configuration : IPluginConfiguration { public bool FilterIncludePreviousSessions; public bool SharedMode; + public bool FontsEnabled = true; public float FontSize = 17f; public float JapaneseFontSize = 17f; public float SymbolsFontSize = 17f; @@ -66,6 +67,7 @@ internal class Configuration : IPluginConfiguration { this.LoadPreviousSession = other.LoadPreviousSession; this.FilterIncludePreviousSessions = other.FilterIncludePreviousSessions; this.SharedMode = other.SharedMode; + this.FontsEnabled = other.FontsEnabled; this.FontSize = other.FontSize; this.JapaneseFontSize = other.JapaneseFontSize; this.SymbolsFontSize = other.SymbolsFontSize; diff --git a/ChatTwo/GameFunctions/Chat.cs b/ChatTwo/GameFunctions/Chat.cs index 6064efe..1d202f1 100755 --- a/ChatTwo/GameFunctions/Chat.cs +++ b/ChatTwo/GameFunctions/Chat.cs @@ -34,7 +34,7 @@ internal sealed unsafe class Chat : IDisposable { [Signature("E8 ?? ?? ?? ?? 48 3B F0 74 35")] private readonly delegate* unmanaged _getFocus = null!; - [Signature("44 8B 89 ?? ?? ?? ?? 4C 8B C1")] + [Signature("44 8B 89 ?? ?? ?? ?? 4C 8B C1 45 85 C9")] private readonly delegate* unmanaged _getTellHistory = null!; [Signature("E8 ?? ?? ?? ?? B8 ?? ?? ?? ?? 48 8D 4D 50")] diff --git a/ChatTwo/GameFunctions/Context.cs b/ChatTwo/GameFunctions/Context.cs index 90d31b1..0a7abf5 100755 --- a/ChatTwo/GameFunctions/Context.cs +++ b/ChatTwo/GameFunctions/Context.cs @@ -87,8 +87,8 @@ internal sealed unsafe class Context { } var uiModule = Framework.Instance()->GetUiModule(); - var vf35 = (delegate* unmanaged) uiModule->vfunc[35]; - var a1 = vf35(uiModule); + var vf36 = (delegate* unmanaged) uiModule->vfunc[36]; + var a1 = vf36(uiModule); this._searchForRecipesUsingItem(a1, itemId); } diff --git a/ChatTwo/GameFunctions/GameFunctions.cs b/ChatTwo/GameFunctions/GameFunctions.cs index 3a57428..9ecf503 100755 --- a/ChatTwo/GameFunctions/GameFunctions.cs +++ b/ChatTwo/GameFunctions/GameFunctions.cs @@ -30,7 +30,7 @@ internal unsafe class GameFunctions : IDisposable { [Signature("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 E8 ?? ?? ?? ?? 48 8B 8B ?? ?? ?? ?? 48 85 C9", Fallibility = Fallibility.Fallible)] private readonly delegate* unmanaged _openPartyFinder = null!; - [Signature("E8 ?? ?? ?? ?? EB 42 48 8B 47 30", Fallibility = Fallibility.Fallible)] + [Signature("E8 ?? ?? ?? ?? EB 20 48 8B 46 28", Fallibility = Fallibility.Fallible)] private readonly delegate* unmanaged _openAchievement = null!; #endregion @@ -164,27 +164,27 @@ internal unsafe class GameFunctions : IDisposable { var agentPtr = (IntPtr) agent; - // addresses mentioned here are 6.01 + // addresses mentioned here are 6.11 // see the call near the end of AgentItemDetail.Update - // offsets valid as of 6.01 + // offsets valid as of 6.11 - // 8BFC49: sets some shit + // A54B19: sets some shit *(uint*) (agentPtr + 0x20) = 22; - // 8C04C8: switch goes down to default, which is what we want + // A55218: switch goes down to default, which is what we want *(byte*) (agentPtr + 0x118) = 1; - // 8BFCF6: item id when hovering over item in chat + // A54BE0: item id when hovering over item in chat *(uint*) (agentPtr + 0x11C) = id; - // 8BFCE4: always 0 when hovering over item in chat + // A54BCC: always 0 when hovering over item in chat *(uint*) (agentPtr + 0x120) = 0; - // 8C0B55: skips a check to do with inventory + // A558A5: skips a check to do with inventory *(byte*) (agentPtr + 0x128) &= 0xEF; - // 8BFC7C: when set to 1, lets everything continue (one frame) - *(byte*) (agentPtr + 0x146) = 1; - // 8BFC89: skips early return - *(byte*) (agentPtr + 0x14A) = 0; + // A54B3F: when set to 1, lets everything continue (one frame) + *(byte*) (agentPtr + 0x14A) = 1; + // A54B59: skips early return + *(byte*) (agentPtr + 0x14E) = 0; // this just probably needs to be set - agent->AddonId = (uint) addon->ID; + agent->AddonId = addon->ID; // vcall from E8 ?? ?? ?? ?? 0F B7 C0 48 83 C4 60 var vf5 = (delegate* unmanaged*) ((IntPtr) addon->VTable + 40); diff --git a/ChatTwo/GameFunctions/Party.cs b/ChatTwo/GameFunctions/Party.cs index 3031d8a..58bdf47 100755 --- a/ChatTwo/GameFunctions/Party.cs +++ b/ChatTwo/GameFunctions/Party.cs @@ -31,7 +31,7 @@ internal sealed unsafe class Party { return; } - // 6.05: 20D722 + // 6.11: 214A55 var a1 = this.Plugin.Functions.GetInfoProxyByIndex(1); fixed (byte* namePtr = name.ToTerminatedBytes()) { // this only works if target is on the same world @@ -44,7 +44,7 @@ internal sealed unsafe class Party { return; } - // 6.05: 20D722 + // 6.11: 214A55 var a1 = this.Plugin.Functions.GetInfoProxyByIndex(1); if (contentId != 0) { // third param is world, but it requires a specific world diff --git a/ChatTwo/PluginUi.cs b/ChatTwo/PluginUi.cs index 892e538..42e66f8 100755 --- a/ChatTwo/PluginUi.cs +++ b/ChatTwo/PluginUi.cs @@ -2,6 +2,7 @@ using System.Numerics; using System.Runtime.InteropServices; using ChatTwo.Ui; using Dalamud.Interface; +using Dalamud.Interface.GameFonts; using Dalamud.Logging; using ImGuiNET; @@ -14,6 +15,9 @@ internal sealed class PluginUi : IDisposable { internal bool ScreenshotMode; internal string Salt { get; } + internal GameFontHandle Axis { get; private set; } + internal GameFontHandle AxisItalic { get; private set; } + internal ImFontPtr? RegularFont { get; private set; } internal ImFontPtr? ItalicFont { get; private set; } internal Vector4 DefaultText { get; private set; } @@ -112,7 +116,11 @@ internal sealed class PluginUi : IDisposable { BuildRange(out this._jpRange, GlyphRangesJapanese.GlyphRanges); this.SetUpUserFonts(); - var gameSym = File.ReadAllBytes(Path.Combine(this.Plugin.Interface.DalamudAssetDirectory.FullName, "UIRes", "gamesym.ttf")); + var gameSym = new HttpClient().GetAsync("https://img.finalfantasyxiv.com/lds/pc/global/fonts/FFXIV_Lodestone_SSF.ttf") + .Result + .Content + .ReadAsByteArrayAsync() + .Result; this._gameSymFont = ( GCHandle.Alloc(gameSym, GCHandleType.Pinned), gameSym.Length @@ -165,9 +173,13 @@ internal sealed class PluginUi : IDisposable { this.DefaultText = ImGui.GetStyle().Colors[(int) ImGuiCol.Text]; var font = this.RegularFont.HasValue; + var pushed = font && this.Plugin.Config.FontsEnabled; + var axis = !this.Plugin.Config.FontsEnabled && this.Axis.Available; - if (font) { + if (pushed) { ImGui.PushFont(this.RegularFont!.Value); + } else if (axis) { + ImGui.PushFont(this.Axis.ImFont); } foreach (var component in this.Components) { @@ -178,7 +190,7 @@ internal sealed class PluginUi : IDisposable { } } - if (font) { + if (pushed || axis) { ImGui.PopFont(); } } @@ -274,6 +286,11 @@ internal sealed class PluginUi : IDisposable { this.SetUpUserFonts(); + this.Axis = this.Plugin.Interface.UiBuilder.GetGameFontHandle(new GameFontStyle(GameFontFamily.Axis, this.Plugin.Config.FontSize)); + this.AxisItalic = this.Plugin.Interface.UiBuilder.GetGameFontHandle(new GameFontStyle(GameFontFamily.Axis, this.Plugin.Config.FontSize) { + SkewStrength = this.Plugin.Config.FontSize / 6, + }); + // load regular noto sans and merge in jp + game icons this.RegularFont = ImGui.GetIO().Fonts.AddFontFromMemoryTTF( this._regularFont.Item1.AddrOfPinnedObject(), diff --git a/ChatTwo/Resources/Language.Designer.cs b/ChatTwo/Resources/Language.Designer.cs index 14c1a17..5d24af5 100755 --- a/ChatTwo/Resources/Language.Designer.cs +++ b/ChatTwo/Resources/Language.Designer.cs @@ -519,6 +519,15 @@ namespace ChatTwo.Resources { } } + /// + /// Looks up a localized string similar to Enable custom fonts. + /// + internal static string Options_FontsEnabled { + get { + return ResourceManager.GetString("Options_FontsEnabled", resourceCulture); + } + } + /// /// Looks up a localized string similar to Font size. /// diff --git a/ChatTwo/Resources/Language.resx b/ChatTwo/Resources/Language.resx index 2696338..133c427 100755 --- a/ChatTwo/Resources/Language.resx +++ b/ChatTwo/Resources/Language.resx @@ -494,4 +494,7 @@ Opacity + + Enable custom fonts + diff --git a/ChatTwo/Ui/ChatLog.cs b/ChatTwo/Ui/ChatLog.cs index a27f37f..44775ad 100755 --- a/ChatTwo/Ui/ChatLog.cs +++ b/ChatTwo/Ui/ChatLog.cs @@ -39,12 +39,14 @@ internal sealed class ChatLog : IUiComponent { private PayloadHandler PayloadHandler { get; } private Dictionary TextCommandChannels { get; } = new(); + private HashSet AllCommands { get; } = new(); internal ChatLog(PluginUi ui) { this.Ui = ui; this.PayloadHandler = new PayloadHandler(this.Ui, this); this.SetUpTextCommandChannels(); + this.SetUpAllCommands(); this.Ui.Plugin.Commands.Register("/clearlog2", "Clear the Chat 2 chat log").Execute += this.ClearLog; this.Ui.Plugin.Commands.Register("/chat2").Execute += this.ToggleChat; @@ -137,6 +139,11 @@ internal sealed class ChatLog : IUiComponent { } } + private bool IsValidCommand(string command) { + return this.Ui.Plugin.CommandManager.Commands.ContainsKey(command) + || this.AllCommands.Contains(command); + } + private void ClearLog(string command, string arguments) { switch (arguments) { case "all": @@ -213,6 +220,23 @@ internal sealed class ChatLog : IUiComponent { this.TextCommandChannels[command.ShortAlias] = type; } + private void SetUpAllCommands() { + if (this.Ui.Plugin.DataManager.GetExcelSheet() is not { } commands) { + return; + } + + var commandNames = commands.SelectMany(cmd => new[] { + cmd.Command.RawString, + cmd.ShortCommand.RawString, + cmd.Alias.RawString, + cmd.ShortAlias.RawString, + }); + + foreach (var command in commandNames) { + this.AllCommands.Add(command); + } + } + private void AddBacklog(string message) { for (var i = 0; i < this._inputBacklog.Count; i++) { if (this._inputBacklog[i] != message) { @@ -479,6 +503,10 @@ internal sealed class ChatLog : IUiComponent { if (this.TextCommandChannels.TryGetValue(command, out var channel)) { inputType = channel; } + + if (!this.IsValidCommand(command)) { + inputType = ChatType.Error; + } } var normalColour = *ImGui.GetStyleColorVec4(ImGuiCol.Text); @@ -1040,8 +1068,17 @@ internal sealed class ChatLog : IUiComponent { ImGui.PushStyleColor(ImGuiCol.Text, colour.Value); } - if (text.Italic && this.Ui.ItalicFont.HasValue) { - ImGui.PushFont(this.Ui.ItalicFont.Value); + var pushed = false; + if (text.Italic) { + if (this.Ui.ItalicFont.HasValue && this.Ui.Plugin.Config.FontsEnabled) { + ImGui.PushFont(this.Ui.ItalicFont.Value); + pushed = true; + } + + if (!this.Ui.Plugin.Config.FontsEnabled && this.Ui.AxisItalic.Available) { + ImGui.PushFont(this.Ui.AxisItalic.ImFont); + pushed = true; + } } var content = text.Content; @@ -1062,7 +1099,7 @@ internal sealed class ChatLog : IUiComponent { ImGuiUtil.PostPayload(chunk, handler); } - if (text.Italic && this.Ui.ItalicFont.HasValue) { + if (pushed) { ImGui.PopFont(); } diff --git a/ChatTwo/Ui/SettingsTabs/Fonts.cs b/ChatTwo/Ui/SettingsTabs/Fonts.cs index 1dec4ac..36b769a 100755 --- a/ChatTwo/Ui/SettingsTabs/Fonts.cs +++ b/ChatTwo/Ui/SettingsTabs/Fonts.cs @@ -27,66 +27,71 @@ public class Fonts : ISettingsTab { } ImGui.PushTextWrapPos(); - - if (ImGuiUtil.BeginComboVertical(Language.Options_Font_Name, this.Mutable.GlobalFont)) { - foreach (var font in Ui.Fonts.GlobalFonts) { - if (ImGui.Selectable(font.Name, this.Mutable.GlobalFont == font.Name)) { - this.Mutable.GlobalFont = font.Name; - } - - if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == font.Name) { - ImGui.SetScrollHereY(0.5f); - } - } - - ImGui.Separator(); - - foreach (var name in this.GlobalFonts) { - if (ImGui.Selectable(name, this.Mutable.GlobalFont == name)) { - this.Mutable.GlobalFont = name; - } - - if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == name) { - ImGui.SetScrollHereY(0.5f); - } - } - - ImGui.EndCombo(); - } - - ImGuiUtil.HelpText(string.Format(Language.Options_Font_Description, Plugin.PluginName)); - ImGuiUtil.WarningText(Language.Options_Font_Warning); + + ImGui.Checkbox(Language.Options_FontsEnabled, ref this.Mutable.FontsEnabled); ImGui.Spacing(); - if (ImGuiUtil.BeginComboVertical(Language.Options_JapaneseFont_Name, this.Mutable.JapaneseFont)) { - foreach (var (name, _) in Ui.Fonts.JapaneseFonts) { - if (ImGui.Selectable(name, this.Mutable.JapaneseFont == name)) { - this.Mutable.JapaneseFont = name; + if (this.Mutable.FontsEnabled) { + if (ImGuiUtil.BeginComboVertical(Language.Options_Font_Name, this.Mutable.GlobalFont)) { + foreach (var font in Ui.Fonts.GlobalFonts) { + if (ImGui.Selectable(font.Name, this.Mutable.GlobalFont == font.Name)) { + this.Mutable.GlobalFont = font.Name; + } + + if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == font.Name) { + ImGui.SetScrollHereY(0.5f); + } } - if (ImGui.IsWindowAppearing() && this.Mutable.JapaneseFont == name) { - ImGui.SetScrollHereY(0.5f); + ImGui.Separator(); + + foreach (var name in this.GlobalFonts) { + if (ImGui.Selectable(name, this.Mutable.GlobalFont == name)) { + this.Mutable.GlobalFont = name; + } + + if (ImGui.IsWindowAppearing() && this.Mutable.GlobalFont == name) { + ImGui.SetScrollHereY(0.5f); + } } + + ImGui.EndCombo(); } - ImGui.Separator(); + ImGuiUtil.HelpText(string.Format(Language.Options_Font_Description, Plugin.PluginName)); + ImGuiUtil.WarningText(Language.Options_Font_Warning); + ImGui.Spacing(); - foreach (var family in this.JpFonts) { - if (ImGui.Selectable(family, this.Mutable.JapaneseFont == family)) { - this.Mutable.JapaneseFont = family; + if (ImGuiUtil.BeginComboVertical(Language.Options_JapaneseFont_Name, this.Mutable.JapaneseFont)) { + foreach (var (name, _) in Ui.Fonts.JapaneseFonts) { + if (ImGui.Selectable(name, this.Mutable.JapaneseFont == name)) { + this.Mutable.JapaneseFont = name; + } + + if (ImGui.IsWindowAppearing() && this.Mutable.JapaneseFont == name) { + ImGui.SetScrollHereY(0.5f); + } } - if (ImGui.IsWindowAppearing() && this.Mutable.JapaneseFont == family) { - ImGui.SetScrollHereY(0.5f); + ImGui.Separator(); + + foreach (var family in this.JpFonts) { + if (ImGui.Selectable(family, this.Mutable.JapaneseFont == family)) { + this.Mutable.JapaneseFont = family; + } + + if (ImGui.IsWindowAppearing() && this.Mutable.JapaneseFont == family) { + ImGui.SetScrollHereY(0.5f); + } } + + ImGui.EndCombo(); } - ImGui.EndCombo(); + ImGuiUtil.HelpText(string.Format(Language.Options_JapaneseFont_Description, Plugin.PluginName)); + ImGui.Spacing(); } - ImGuiUtil.HelpText(string.Format(Language.Options_JapaneseFont_Description, Plugin.PluginName)); - ImGui.Spacing(); - const float speed = .0125f; const float min = 8f; const float max = 36f;