diff --git a/.nuke b/.nuke new file mode 100644 index 000000000..c37461139 --- /dev/null +++ b/.nuke @@ -0,0 +1 @@ +Dalamud.sln \ No newline at end of file diff --git a/Dalamud.Bootstrap/Crypto/Blowfish.cs b/Dalamud.Bootstrap/Crypto/Blowfish.cs index 2b3b41469..8d58c1cbb 100644 --- a/Dalamud.Bootstrap/Crypto/Blowfish.cs +++ b/Dalamud.Bootstrap/Crypto/Blowfish.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers.Binary; using System.Runtime.CompilerServices; namespace Dalamud.Bootstrap.Crypto diff --git a/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj b/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj index a28f10736..388b565ca 100644 --- a/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj +++ b/Dalamud.Bootstrap/Dalamud.Bootstrap.csproj @@ -5,8 +5,13 @@ preview enable true + true + + + + diff --git a/Dalamud.Bootstrap/SqexArg/ArgumentContainer.cs b/Dalamud.Bootstrap/SqexArg/ArgumentContainer.cs index c6e9216bb..4bd85fdad 100644 --- a/Dalamud.Bootstrap/SqexArg/ArgumentContainer.cs +++ b/Dalamud.Bootstrap/SqexArg/ArgumentContainer.cs @@ -26,14 +26,14 @@ namespace Dalamud.Bootstrap.SqexArg } var checksum = argument[^5]; - var payload = argument[11..^5] - .Replace(; // encoded in url-safe variant of base64 + var payload = argument[11..^5]; // decode - Convert.FromBase64String(); - container = new ArgumentContainer(payload, checksum); + //Convert.FromBase64String(); + //container = new ArgumentContainer(payload, checksum); + container = null; return true; } } diff --git a/Dalamud.sln b/Dalamud.sln index 83bb6fe78..fd0389e44 100644 --- a/Dalamud.sln +++ b/Dalamud.sln @@ -7,22 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud", "Dalamud\Dalamud. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud.Injector", "Dalamud.Injector\Dalamud.Injector.csproj", "{5B832F73-5F54-4ADC-870F-D0095EF72C9A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImGuiScene", "lib\ImGuiScene\ImGuiScene\ImGuiScene.csproj", "{C0E7E797-4FBF-4F46-BC57-463F3719BA7A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SDL2-CS", "lib\ImGuiScene\deps\SDL2-CS\SDL2-CS.csproj", "{85480198-8711-4355-830E-72FD794AD3F6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImGui.NET-472", "lib\ImGuiScene\deps\ImGui.NET\src\ImGui.NET-472\ImGui.NET-472.csproj", "{0483026E-C6CE-4B1A-AA68-46544C08140B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interface", "Interface", "{E15BDA6D-E881-4482-94BA-BE5527E917FF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DiscordNet", "DiscordNet", "{E1F3D3F5-7820-4A62-A16A-53260375A781}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Rest", "lib\Discord.Net\src\Discord.Net.Rest\Discord.Net.Rest.csproj", "{10E4E5CB-F51E-42EC-B98C-FBCE839D4624}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.Core", "lib\Discord.Net\src\Discord.Net.Core\Discord.Net.Core.csproj", "{B46F33B5-9702-434E-A92C-8DE5CF7164E3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Discord.Net.WebSocket", "lib\Discord.Net\src\Discord.Net.WebSocket\Discord.Net.WebSocket.csproj", "{AACDC15A-56F8-458F-9C73-DE89F60466AE}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{E9868930-4223-4D57-8F31-84E580E4B24B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CoreHook", "CoreHook", "{CE78D902-02B5-4C7B-A46A-D44BD2F4C622}" @@ -39,9 +23,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreHook.IPC", "lib\CoreHoo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CoreHook.Memory", "lib\CoreHook\src\CoreHook.Memory\CoreHook.Memory.csproj", "{ED4FFE13-5F83-42B9-8847-E7C4D7A988E8}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Bootstrap", "Dalamud.Bootstrap\Dalamud.Bootstrap.csproj", "{19032128-E336-460F-B6E4-EAF6055589E5}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud.Bootstrap", "Dalamud.Bootstrap\Dalamud.Bootstrap.csproj", "{19032128-E336-460F-B6E4-EAF6055589E5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dalamud.Testing", "Dalamud.Testing\Dalamud.Testing.csproj", "{0A99A6B3-12E2-4197-A6F3-9211B6D4D824}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dalamud.Testing", "Dalamud.Testing\Dalamud.Testing.csproj", "{0A99A6B3-12E2-4197-A6F3-9211B6D4D824}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Build", "build\Build.csproj", "{A6BB70E8-7F14-410F-A296-1B4495F6F069}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -77,78 +63,6 @@ Global {5B832F73-5F54-4ADC-870F-D0095EF72C9A}.Release|x64.Build.0 = Release|Any CPU {5B832F73-5F54-4ADC-870F-D0095EF72C9A}.Release|x86.ActiveCfg = Release|Any CPU {5B832F73-5F54-4ADC-870F-D0095EF72C9A}.Release|x86.Build.0 = Release|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|x64.ActiveCfg = Debug|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|x64.Build.0 = Debug|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|x86.ActiveCfg = Debug|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Debug|x86.Build.0 = Debug|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|Any CPU.Build.0 = Release|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|x64.ActiveCfg = Release|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|x64.Build.0 = Release|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|x86.ActiveCfg = Release|Any CPU - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A}.Release|x86.Build.0 = Release|Any CPU - {85480198-8711-4355-830E-72FD794AD3F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {85480198-8711-4355-830E-72FD794AD3F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {85480198-8711-4355-830E-72FD794AD3F6}.Debug|x64.ActiveCfg = Debug|x64 - {85480198-8711-4355-830E-72FD794AD3F6}.Debug|x64.Build.0 = Debug|x64 - {85480198-8711-4355-830E-72FD794AD3F6}.Debug|x86.ActiveCfg = Debug|x86 - {85480198-8711-4355-830E-72FD794AD3F6}.Debug|x86.Build.0 = Debug|x86 - {85480198-8711-4355-830E-72FD794AD3F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {85480198-8711-4355-830E-72FD794AD3F6}.Release|Any CPU.Build.0 = Release|Any CPU - {85480198-8711-4355-830E-72FD794AD3F6}.Release|x64.ActiveCfg = Release|x64 - {85480198-8711-4355-830E-72FD794AD3F6}.Release|x64.Build.0 = Release|x64 - {85480198-8711-4355-830E-72FD794AD3F6}.Release|x86.ActiveCfg = Release|x86 - {85480198-8711-4355-830E-72FD794AD3F6}.Release|x86.Build.0 = Release|x86 - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|x64.ActiveCfg = Debug|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|x64.Build.0 = Debug|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|x86.ActiveCfg = Debug|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Debug|x86.Build.0 = Debug|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|Any CPU.Build.0 = Release|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|x64.ActiveCfg = Release|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|x64.Build.0 = Release|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|x86.ActiveCfg = Release|Any CPU - {0483026E-C6CE-4B1A-AA68-46544C08140B}.Release|x86.Build.0 = Release|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Debug|Any CPU.Build.0 = Debug|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Debug|x64.ActiveCfg = Debug|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Debug|x64.Build.0 = Debug|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Debug|x86.ActiveCfg = Debug|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Debug|x86.Build.0 = Debug|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Release|Any CPU.ActiveCfg = Release|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Release|Any CPU.Build.0 = Release|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Release|x64.ActiveCfg = Release|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Release|x64.Build.0 = Release|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Release|x86.ActiveCfg = Release|Any CPU - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624}.Release|x86.Build.0 = Release|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Debug|x64.ActiveCfg = Debug|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Debug|x64.Build.0 = Debug|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Debug|x86.ActiveCfg = Debug|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Debug|x86.Build.0 = Debug|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Release|Any CPU.Build.0 = Release|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Release|x64.ActiveCfg = Release|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Release|x64.Build.0 = Release|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Release|x86.ActiveCfg = Release|Any CPU - {B46F33B5-9702-434E-A92C-8DE5CF7164E3}.Release|x86.Build.0 = Release|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Debug|x64.ActiveCfg = Debug|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Debug|x64.Build.0 = Debug|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Debug|x86.ActiveCfg = Debug|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Debug|x86.Build.0 = Debug|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Release|Any CPU.Build.0 = Release|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Release|x64.ActiveCfg = Release|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Release|x64.Build.0 = Release|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Release|x86.ActiveCfg = Release|Any CPU - {AACDC15A-56F8-458F-9C73-DE89F60466AE}.Release|x86.Build.0 = Release|Any CPU {441EE8F0-AD8E-479B-9F68-12D157F080AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {441EE8F0-AD8E-479B-9F68-12D157F080AF}.Debug|Any CPU.Build.0 = Debug|Any CPU {441EE8F0-AD8E-479B-9F68-12D157F080AF}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -245,19 +159,21 @@ Global {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x64.Build.0 = Release|Any CPU {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x86.ActiveCfg = Release|Any CPU {0A99A6B3-12E2-4197-A6F3-9211B6D4D824}.Release|x86.Build.0 = Release|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Debug|x64.ActiveCfg = Debug|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Debug|x64.Build.0 = Debug|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Debug|x86.ActiveCfg = Debug|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Debug|x86.Build.0 = Debug|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Release|x64.ActiveCfg = Release|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Release|x64.Build.0 = Release|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Release|x86.ActiveCfg = Release|Any CPU + {A6BB70E8-7F14-410F-A296-1B4495F6F069}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {C0E7E797-4FBF-4F46-BC57-463F3719BA7A} = {E15BDA6D-E881-4482-94BA-BE5527E917FF} - {85480198-8711-4355-830E-72FD794AD3F6} = {E15BDA6D-E881-4482-94BA-BE5527E917FF} - {0483026E-C6CE-4B1A-AA68-46544C08140B} = {E15BDA6D-E881-4482-94BA-BE5527E917FF} - {E15BDA6D-E881-4482-94BA-BE5527E917FF} = {E9868930-4223-4D57-8F31-84E580E4B24B} - {E1F3D3F5-7820-4A62-A16A-53260375A781} = {E9868930-4223-4D57-8F31-84E580E4B24B} - {10E4E5CB-F51E-42EC-B98C-FBCE839D4624} = {E1F3D3F5-7820-4A62-A16A-53260375A781} - {B46F33B5-9702-434E-A92C-8DE5CF7164E3} = {E1F3D3F5-7820-4A62-A16A-53260375A781} - {AACDC15A-56F8-458F-9C73-DE89F60466AE} = {E1F3D3F5-7820-4A62-A16A-53260375A781} {CE78D902-02B5-4C7B-A46A-D44BD2F4C622} = {E9868930-4223-4D57-8F31-84E580E4B24B} {441EE8F0-AD8E-479B-9F68-12D157F080AF} = {CE78D902-02B5-4C7B-A46A-D44BD2F4C622} {91CB76FC-8E4B-4B4C-B5AD-D681866A2188} = {CE78D902-02B5-4C7B-A46A-D44BD2F4C622} diff --git a/Dalamud/Configuration/DalamudConfiguration.cs b/Dalamud/Configuration/DalamudConfiguration.cs deleted file mode 100644 index 486948b11..000000000 --- a/Dalamud/Configuration/DalamudConfiguration.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using Dalamud.Configuration; -using Dalamud.DiscordBot; -using Newtonsoft.Json; - -namespace Dalamud -{ - [Serializable] - public class DalamudConfiguration - { - public DiscordFeatureConfiguration DiscordFeatureConfig { get; set; } - - public bool OptOutMbCollection { get; set; } = false; - - public List BadWords { get; set; } - - public enum PreferredRole - { - None, - All, - Tank, - Dps, - Healer - } - - public Dictionary PreferredRoleReminders { get; set; } - - public string LastVersion { get; set; } - - public Dictionary PluginConfigurations { get; set; } - - public static DalamudConfiguration Load(string path) { - return JsonConvert.DeserializeObject(File.ReadAllText(path)); - } - - public void Save(string path) { - File.WriteAllText(path, JsonConvert.SerializeObject(this)); - } - } -} diff --git a/Dalamud/Configuration/IPluginConfiguration.cs b/Dalamud/Configuration/IPluginConfiguration.cs deleted file mode 100644 index f2a782960..000000000 --- a/Dalamud/Configuration/IPluginConfiguration.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Configuration -{ - public interface IPluginConfiguration - { - int Version { get; set; } - } -} diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs deleted file mode 100644 index 20a4fe595..000000000 --- a/Dalamud/Dalamud.cs +++ /dev/null @@ -1,575 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Dalamud.Data; -using Dalamud.DiscordBot; -using Dalamud.Game; -using Dalamud.Game.Chat; -using Dalamud.Game.ClientState; -using Dalamud.Game.ClientState.Actors.Types; -using Dalamud.Game.ClientState.Actors.Types.NonPlayer; -using Dalamud.Game.Command; -using Dalamud.Game.Internal; -using Dalamud.Game.Internal.Gui; -using Dalamud.Game.Network; -using Dalamud.Interface; -using Dalamud.Plugin; -using ImGuiNET; -using Serilog; - -namespace Dalamud { - public sealed class Dalamud : IDisposable { - private readonly string baseDirectory; - - private readonly ManualResetEvent unloadSignal; - - private readonly ProcessModule targetModule; - - public readonly SigScanner SigScanner; - - public readonly Framework Framework; - - public readonly CommandManager CommandManager; - - public readonly ChatHandlers ChatHandlers; - - public readonly NetworkHandlers NetworkHandlers; - - public readonly DiscordBotManager BotManager; - - public readonly PluginManager PluginManager; - - public readonly ClientState ClientState; - - public readonly DalamudStartInfo StartInfo; - - public readonly DalamudConfiguration Configuration; - - private readonly WinSockHandlers WinSock2; - - public readonly InterfaceManager InterfaceManager; - - public readonly DataManager Data; - - private readonly string assemblyVersion = Assembly.GetAssembly(typeof(ChatHandlers)).GetName().Version.ToString(); - - public Dalamud(DalamudStartInfo info) { - this.StartInfo = info; - this.Configuration = DalamudConfiguration.Load(info.ConfigurationPath); - - this.baseDirectory = info.WorkingDirectory; - - this.unloadSignal = new ManualResetEvent(false); - - // Initialize the process information. - this.targetModule = Process.GetCurrentProcess().MainModule; - this.SigScanner = new SigScanner(this.targetModule, true); - - // Initialize game subsystem - this.Framework = new Framework(this.SigScanner, this); - - // Initialize managers. Basically handlers for the logic - this.CommandManager = new CommandManager(this, info.Language); - SetupCommands(); - - this.ChatHandlers = new ChatHandlers(this); - this.NetworkHandlers = new NetworkHandlers(this, this.Configuration.OptOutMbCollection); - - this.Data = new DataManager(this.StartInfo.Language); - this.Data.Initialize(); - - this.ClientState = new ClientState(this, info, this.SigScanner, this.targetModule); - - this.BotManager = new DiscordBotManager(this, this.Configuration.DiscordFeatureConfig); - - this.PluginManager = new PluginManager(this, info.PluginDirectory); - - this.WinSock2 = new WinSockHandlers(); - - try { - this.InterfaceManager = new InterfaceManager(this, this.SigScanner); - this.InterfaceManager.OnDraw += BuildDalamudUi; - } catch (Exception e) { - Log.Information(e, "Could not init interface."); - } - } - - public void Start() { - try { - this.InterfaceManager?.Enable(); - } catch (Exception e) { - Log.Information("Could not enable interface."); - } - - this.Framework.Enable(); - - this.BotManager.Start(); - - try { - this.PluginManager.LoadPlugins(); - } catch (Exception ex) { - this.Framework.Gui.Chat.PrintError( - "[XIVLAUNCHER] There was an error loading additional plugins. Please check the log for more details."); - Log.Error(ex, "Plugin load failed."); - } - } - - public void Unload() { - this.unloadSignal.Set(); - } - - public void WaitForUnload() { - this.unloadSignal.WaitOne(); - } - - public void Dispose() { - try - { - this.PluginManager.UnloadPlugins(); - } - catch (Exception ex) - { - Framework.Gui.Chat.PrintError( - "[XIVLAUNCHER] There was an error unloading additional plugins. Please check the log for more details."); - Log.Error(ex, "Plugin unload failed."); - } - - this.InterfaceManager.Dispose(); - - Framework.Dispose(); - - this.BotManager.Dispose(); - - this.unloadSignal.Dispose(); - - this.WinSock2.Dispose(); - - this.SigScanner.Dispose(); - } - - #region Interface - - private bool isImguiDrawDemoWindow = false; - -#if DEBUG - private bool isImguiDrawDevMenu = true; -#else - private bool isImguiDrawDevMenu = false; -#endif - - private bool isImguiDrawLogWindow = false; - private bool isImguiDrawDataWindow = false; - private bool isImguiDrawPluginWindow = false; - - private DalamudLogWindow logWindow; - private DalamudDataWindow dataWindow; - private PluginInstallerWindow pluginWindow; - - private void BuildDalamudUi() - { - if (this.isImguiDrawDevMenu) - { - if (ImGui.BeginMainMenuBar()) - { - if (ImGui.BeginMenu("Dalamud")) - { - ImGui.MenuItem("Draw Dalamud dev menu", "", ref this.isImguiDrawDevMenu); - ImGui.Separator(); - if (ImGui.MenuItem("Open Log window")) - { - this.logWindow = new DalamudLogWindow(); - this.isImguiDrawLogWindow = true; - } - if (ImGui.MenuItem("Open Data window")) - { - this.dataWindow = new DalamudDataWindow(this.Data); - this.isImguiDrawDataWindow = true; - } - ImGui.MenuItem("Draw ImGui demo", "", ref this.isImguiDrawDemoWindow); - ImGui.Separator(); - if (ImGui.MenuItem("Unload Dalamud")) - { - Unload(); - } - if (ImGui.MenuItem("Kill game")) - { - Process.GetCurrentProcess().Kill(); - } - ImGui.Separator(); - ImGui.MenuItem(this.assemblyVersion, false); - - ImGui.EndMenu(); - } - - if (ImGui.BeginMenu("Plugins")) - { - if (ImGui.MenuItem("Open Plugin installer")) - { - this.pluginWindow = new PluginInstallerWindow(this.PluginManager, this.StartInfo.PluginDirectory); - this.isImguiDrawPluginWindow = true; - } - if (ImGui.MenuItem("Print plugin info")) { - foreach (var plugin in this.PluginManager.Plugins) { - // TODO: some more here, state maybe? - Log.Information($"{plugin.Plugin.Name}"); - } - } - if (ImGui.MenuItem("Reload plugins")) - { - OnPluginReloadCommand(string.Empty, string.Empty); - } - ImGui.EndMenu(); - } - - ImGui.EndMainMenuBar(); - } - } - - if (this.isImguiDrawLogWindow) - { - this.isImguiDrawLogWindow = this.logWindow != null && this.logWindow.Draw(); - - if (this.isImguiDrawLogWindow == false) - { - this.logWindow?.Dispose(); - } - } - - if (this.isImguiDrawDataWindow) - { - this.isImguiDrawDataWindow = this.dataWindow != null && this.dataWindow.Draw(); - } - - if (this.isImguiDrawPluginWindow) - { - this.isImguiDrawPluginWindow = this.pluginWindow != null && this.pluginWindow.Draw(); - } - - if (this.isImguiDrawDemoWindow) - ImGui.ShowDemoWindow(); - } - - #endregion - - private void SetupCommands() { - CommandManager.AddHandler("/xldclose", new CommandInfo(OnUnloadCommand) { - HelpMessage = "Unloads XIVLauncher in-game addon.", - ShowInHelp = false - }); - - CommandManager.AddHandler("/xldreloadplugins", new CommandInfo(OnPluginReloadCommand) { - HelpMessage = "Reloads all plugins.", - ShowInHelp = false - }); - - CommandManager.AddHandler("/xldsay", new CommandInfo(OnCommandDebugSay) { - HelpMessage = "Print to chat.", - ShowInHelp = false - }); - - CommandManager.AddHandler("/xlhelp", new CommandInfo(OnHelpCommand) { - HelpMessage = "Shows list of commands available." - }); - - CommandManager.AddHandler("/xlmute", new CommandInfo(OnBadWordsAddCommand) { - HelpMessage = "Mute a word or sentence from appearing in chat. Usage: /xlmute " - }); - - CommandManager.AddHandler("/xlmutelist", new CommandInfo(OnBadWordsListCommand) { - HelpMessage = "List muted words or sentences." - }); - - CommandManager.AddHandler("/xlunmute", new CommandInfo(OnBadWordsRemoveCommand) { - HelpMessage = "Unmute a word or sentence. Usage: /xlunmute " - }); - - CommandManager.AddHandler("/xldstate", new CommandInfo(OnDebugPrintGameStateCommand) { - HelpMessage = "Print parsed game state", - ShowInHelp = false - }); - - CommandManager.AddHandler("/ll", new CommandInfo(OnLastLinkCommand) { - HelpMessage = "Open the last posted link in your default browser." - }); - - CommandManager.AddHandler("/xlbotjoin", new CommandInfo(OnBotJoinCommand) { - HelpMessage = "Add the XIVLauncher discord bot you set up to your server." - }); - - CommandManager.AddHandler("/xlbgmset", new CommandInfo(OnBgmSetCommand) - { - HelpMessage = "Set the Game background music. Usage: /xlbgmset " - }); - - CommandManager.AddHandler("/xlitem", new CommandInfo(OnItemLinkCommand) - { - HelpMessage = "Link an item by name. Usage: /xlitem . For matching an item exactly, use /xlitem +" - }); - -#if DEBUG - CommandManager.AddHandler("/xldzpi", new CommandInfo(OnDebugZoneDownInjectCommand) - { - HelpMessage = "Inject zone down channel", - ShowInHelp = false - }); -#endif - - CommandManager.AddHandler("/xlbonus", new CommandInfo(OnRouletteBonusNotifyCommand) - { - HelpMessage = "Notify when a roulette has a bonus you specified. Run without parameters for more info. Usage: /xlbonus " - }); - - CommandManager.AddHandler("/xldev", new CommandInfo(OnDebugDrawDevMenu) { - HelpMessage = "Draw dev menu DEBUG", - ShowInHelp = false - }); - } - - private void OnUnloadCommand(string command, string arguments) { - Framework.Gui.Chat.Print("Unloading..."); - Unload(); - } - - private void OnHelpCommand(string command, string arguments) { - var showDebug = arguments.Contains("debug"); - - Framework.Gui.Chat.Print("Available commands:"); - foreach (var cmd in CommandManager.Commands) { - if (!cmd.Value.ShowInHelp && !showDebug) - continue; - - Framework.Gui.Chat.Print($"{cmd.Key}: {cmd.Value.HelpMessage}"); - } - } - - private void OnCommandDebugSay(string command, string arguments) { - var parts = arguments.Split(); - - var chatType = (XivChatType) int.Parse(parts[0]); - var msg = string.Join(" ", parts.Take(1).ToArray()); - - Framework.Gui.Chat.PrintChat(new XivChatEntry { - MessageBytes = Encoding.UTF8.GetBytes(msg), - Name = "Xiv Launcher", - Type = chatType - }); - } - - private void OnPluginReloadCommand(string command, string arguments) { - Framework.Gui.Chat.Print("Reloading..."); - - try { - this.PluginManager.UnloadPlugins(); - this.PluginManager.LoadPlugins(); - - Framework.Gui.Chat.Print("OK"); - } catch (Exception ex) { - Framework.Gui.Chat.PrintError("Reload failed."); - Log.Error(ex, "Plugin reload failed."); - } - } - - private void OnBadWordsAddCommand(string command, string arguments) { - if (this.Configuration.BadWords == null) - this.Configuration.BadWords = new List(); - - this.Configuration.BadWords.Add(arguments); - - this.Configuration.Save(this.StartInfo.ConfigurationPath); - - Framework.Gui.Chat.Print($"Muted \"{arguments}\"."); - } - - private void OnBadWordsListCommand(string command, string arguments) { - if (this.Configuration.BadWords == null) - this.Configuration.BadWords = new List(); - - if (this.Configuration.BadWords.Count == 0) { - Framework.Gui.Chat.Print("No muted words or sentences."); - return; - } - - this.Configuration.Save(this.StartInfo.ConfigurationPath); - - foreach (var word in this.Configuration.BadWords) Framework.Gui.Chat.Print($"\"{word}\""); - } - - private void OnBadWordsRemoveCommand(string command, string arguments) { - if (this.Configuration.BadWords == null) - this.Configuration.BadWords = new List(); - - this.Configuration.BadWords.RemoveAll(x => x == arguments); - - this.Configuration.Save(this.StartInfo.ConfigurationPath); - - Framework.Gui.Chat.Print($"Unmuted \"{arguments}\"."); - } - - private void OnLastLinkCommand(string command, string arguments) { - if (string.IsNullOrEmpty(ChatHandlers.LastLink)) { - Framework.Gui.Chat.Print("No last link..."); - return; - } - - Framework.Gui.Chat.Print("Opening " + ChatHandlers.LastLink); - Process.Start(ChatHandlers.LastLink); - } - - private void OnDebugPrintGameStateCommand(string command, string arguments) { - Framework.Gui.Chat.Print(this.ClientState.Actors.Length + " entries"); - Framework.Gui.Chat.Print(this.ClientState.LocalPlayer.Name); - Framework.Gui.Chat.Print(this.ClientState.LocalPlayer.CurrentWorld.Name); - Framework.Gui.Chat.Print(this.ClientState.LocalPlayer.HomeWorld.Name); - Framework.Gui.Chat.Print(this.ClientState.LocalContentId.ToString("X")); - Framework.Gui.Chat.Print(Framework.Gui.Chat.LastLinkedItemId.ToString()); - - for (var i = 0; i < this.ClientState.Actors.Length; i++) { - var actor = this.ClientState.Actors[i]; - - Log.Debug(actor.Name); - Framework.Gui.Chat.Print( - $"{i} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}"); - - if (actor is Npc npc) - Framework.Gui.Chat.Print($"DataId: {npc.DataId}"); - - if (actor is Chara chara) - Framework.Gui.Chat.Print( - $"Level: {chara.Level} ClassJob: {chara.ClassJob.Name} CHP: {chara.CurrentHp} MHP: {chara.MaxHp} CMP: {chara.CurrentMp} MMP: {chara.MaxMp}"); - } - } - private void OnBotJoinCommand(string command, string arguments) { - if (this.BotManager != null && this.BotManager.IsConnected) - Process.Start( - $"https://discordapp.com/oauth2/authorize?client_id={this.BotManager.UserId}&scope=bot&permissions=117760"); - else - Framework.Gui.Chat.Print( - "The XIVLauncher discord bot was not set up correctly or could not connect to discord. Please check the settings and the FAQ."); - } - - private void OnBgmSetCommand(string command, string arguments) - { - Framework.Gui.SetBgm(ushort.Parse(arguments)); - } - - private void OnItemLinkCommand(string command, string arguments) { - var exactSearch = false; - if (arguments.StartsWith("+")) - { - exactSearch = true; - arguments = arguments.Substring(1); - } - - Task.Run(async () => { - try { - dynamic results = await XivApi.Search(arguments, "Item", 1, exactSearch); - var itemId = (short) results.Results[0].ID; - var itemName = (string)results.Results[0].Name; - - var hexData = new byte[] { - 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xF3, 0xF3, 0xF3, 0x03, 0x02, 0x27, 0x07, 0x03, 0xF2, 0x3A, 0x2F, - 0x02, 0x01, 0x03, 0x02, 0x13, 0x06, 0xFE, 0xFF, 0xFF, 0x7B, 0x1A, 0x03, 0xEE, 0x82, 0xBB, 0x02, - 0x13, 0x02, 0xEC, 0x03 - }; - - var endTag = new byte[] { - 0x02, 0x27, 0x07, 0xCF, 0x01, 0x01, 0x01, 0xFF, 0x01, 0x03, 0x02, 0x13, 0x02, 0xEC, 0x03 - }; - - BitConverter.GetBytes(itemId).Reverse().ToArray().CopyTo(hexData, 14); - - hexData = hexData.Concat(Encoding.UTF8.GetBytes(itemName)).Concat(endTag).ToArray(); - - Framework.Gui.Chat.PrintChat(new XivChatEntry { - MessageBytes = hexData - }); - } - catch { - Framework.Gui.Chat.PrintError("Could not find item."); - } - - }); - } - -#if DEBUG - private void OnDebugZoneDownInjectCommand(string command, string arguments) { - var data = File.ReadAllBytes(arguments); - - Framework.Network.InjectZoneProtoPacket(data); - Framework.Gui.Chat.Print($"{arguments} OK with {data.Length} bytes"); - } -#endif - - private void OnRouletteBonusNotifyCommand(string command, string arguments) - { - if (this.Configuration.DiscordFeatureConfig.CfPreferredRoleChannel == null) - Framework.Gui.Chat.PrintError("You have not set up a discord channel for these notifications - you will only receive them in chat. To do this, please use the XIVLauncher in-game settings."); - - if (string.IsNullOrEmpty(arguments)) - goto InvalidArgs; - - var argParts = arguments.Split(); - if (argParts.Length < 2) - goto InvalidArgs; - - - if (this.Configuration.PreferredRoleReminders == null) - this.Configuration.PreferredRoleReminders = new Dictionary(); - - var rouletteIndex = RouletteSlugToKey(argParts[0]); - - if (rouletteIndex == 0) - goto InvalidArgs; - - if (!Enum.TryParse(argParts[1].First().ToString().ToUpper() + argParts[1].ToLower().Substring(1), out DalamudConfiguration.PreferredRole role)) - goto InvalidArgs; - - if (this.Configuration.PreferredRoleReminders.ContainsKey(rouletteIndex)) - this.Configuration.PreferredRoleReminders[rouletteIndex] = role; - else - this.Configuration.PreferredRoleReminders.Add(rouletteIndex, role); - - Framework.Gui.Chat.Print($"Set bonus notifications for {argParts[0]}({rouletteIndex}) to {role}"); - this.Configuration.Save(this.StartInfo.ConfigurationPath); - - return; - - InvalidArgs: - Framework.Gui.Chat.PrintError("Unrecognized arguments."); - Framework.Gui.Chat.Print("Possible values for roulette: leveling, 506070, msq, guildhests, expert, trials, mentor, alliance, normal\n" + - "Possible values for role: tank, dps, healer, all, none/reset"); - } - - private void OnDebugDrawDevMenu(string command, string arguments) { - this.isImguiDrawDevMenu = true; - } - - private int RouletteSlugToKey(string slug) => slug.ToLower() switch { - "leveling" => 1, - "506070" => 2, - "msq" => 3, - "guildhests" => 4, - "expert" => 5, - "trials" => 6, - "mentor" => 8, - "alliance" => 9, - "normal" => 10, - _ => 0 - }; - - private DalamudConfiguration.PreferredRole RoleNameToPreferredRole(string name) => name.ToLower() switch - { - "Tank" => DalamudConfiguration.PreferredRole.Tank, - "Healer" => DalamudConfiguration.PreferredRole.Healer, - "Dps" => DalamudConfiguration.PreferredRole.Dps, - "All" => DalamudConfiguration.PreferredRole.All, - _ => DalamudConfiguration.PreferredRole.None - }; - } -} diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj index 257e33532..4cd4a60e2 100644 --- a/Dalamud/Dalamud.csproj +++ b/Dalamud/Dalamud.csproj @@ -5,15 +5,16 @@ preview true enable + true - + + - - + diff --git a/Dalamud/DalamudStartInfo.cs b/Dalamud/DalamudStartInfo.cs deleted file mode 100644 index 16d43e5fa..000000000 --- a/Dalamud/DalamudStartInfo.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using Dalamud.DiscordBot; - -namespace Dalamud { - [Serializable] - public sealed class DalamudStartInfo - { - public string WorkingDirectory; - public string ConfigurationPath; - - public string PluginDirectory; - public string DefaultPluginDirectory; - public ClientLanguage Language; - } - - public enum ClientLanguage - { - Japanese, - English, - German, - French - } -} diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs deleted file mode 100644 index 8f676efae..000000000 --- a/Dalamud/Data/DataManager.cs +++ /dev/null @@ -1,145 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Lumina.Data; -using Lumina.Excel; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Serilog; -using LuminaOptions = Lumina.LuminaOptions; -using ParsedFilePath = Lumina.ParsedFilePath; - -namespace Dalamud.Data -{ - /// - /// This class provides data for Dalamud-internal features, but can also be used by plugins if needed. - /// - public class DataManager { - private const string DataBaseUrl = "https://goaaats.github.io/ffxiv/tools/launcher/addons/Hooks/Data/"; - - public ReadOnlyDictionary ServerOpCodes { get; private set; } - - /// - /// An object which gives access to any of the game's sheet data. - /// - public ExcelModule Excel => this.gameData?.Excel; - - /// - /// Indicates whether Game Data is ready to be read. - /// - public bool IsDataReady { get; private set; } - - /// - /// A object which gives access to any excel/game data. - /// - private Lumina.Lumina gameData; - - private ClientLanguage language; - - public DataManager(ClientLanguage language) - { - // Set up default values so plugins do not null-reference when data is being loaded. - this.ServerOpCodes = new ReadOnlyDictionary(new Dictionary()); - - this.language = language; - } - - public async Task Initialize() - { - try - { - Log.Verbose("Starting data download..."); - - using var client = new HttpClient() - { - BaseAddress = new Uri(DataBaseUrl) - }; - - var opCodeDict = - JsonConvert.DeserializeObject>( - await client.GetStringAsync(DataBaseUrl + "serveropcode.json")); - this.ServerOpCodes = new ReadOnlyDictionary(opCodeDict); - - Log.Verbose("Loaded {0} ServerOpCodes.", opCodeDict.Count); - - - var luminaOptions = new LuminaOptions - { - CacheFileResources = true - }; - - switch (this.language) - { - case ClientLanguage.Japanese: - luminaOptions.DefaultExcelLanguage = Language.Japanese; - break; - case ClientLanguage.English: - luminaOptions.DefaultExcelLanguage = Language.English; - break; - case ClientLanguage.German: - luminaOptions.DefaultExcelLanguage = Language.German; - break; - case ClientLanguage.French: - luminaOptions.DefaultExcelLanguage = Language.French; - break; - default: - throw new ArgumentOutOfRangeException(nameof(this.language), "Unknown Language: " + this.language); - } - - gameData = new Lumina.Lumina(Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "sqpack"), luminaOptions); - - Log.Information("Lumina is ready: {0}", gameData.DataPath); - - IsDataReady = true; - } - catch (Exception ex) - { - Log.Error(ex, "Could not download data."); - } - } - - #region Lumina Wrappers - - /// - /// Get an with the given Excel sheet row type. - /// - /// The excel sheet type to get. - /// The , giving access to game rows. - public ExcelSheet GetExcelSheet() where T : IExcelRow - { - return this.Excel.GetSheet(); - } - - /// - /// Get a with the given path. - /// - /// The path inside of the game files. - /// The of the file. - public FileResource GetFile(string path) - { - return this.GetFile(path); - } - - /// - /// Get a with the given path, of the given type. - /// - /// The type of resource - /// The path inside of the game files. - /// The of the file. - public T GetFile(string path) where T : FileResource - { - ParsedFilePath filePath = Lumina.Lumina.ParseFilePath(path); - if (filePath == null) - return default(T); - Repository repository; - return this.gameData.Repositories.TryGetValue(filePath.Repository, out repository) ? repository.GetFile(filePath.Category, filePath) : default(T); - } - - #endregion - } -} diff --git a/Dalamud/Data/TransientSheet/ContentFinderCondition.cs b/Dalamud/Data/TransientSheet/ContentFinderCondition.cs deleted file mode 100644 index c8b56bfd2..000000000 --- a/Dalamud/Data/TransientSheet/ContentFinderCondition.cs +++ /dev/null @@ -1,610 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Lumina.Excel; - -namespace Dalamud.Data.TransientSheet -{ - [SheetName("ContentFinderCondition")] - public class ContentFinderCondition : IExcelRow - { - // column defs from Thu, 13 Feb 2020 20:46:12 GMT - - /* offset: 002c col: 0 - * name: ShortCode - * type: - */ - - /* offset: 0048 col: 1 - * name: TerritoryType - * type: - */ - - /* offset: 0054 col: 2 - * name: ContentLinkType - * type: - */ - - /* offset: 004a col: 3 - * name: Content - * type: - */ - - /* offset: 0061 col: 4 - * name: PvP - * type: - */ - - /* offset: 0055 col: 5 - * no SaintCoinach definition found - */ - - /* offset: 0030 col: 6 - * no SaintCoinach definition found - */ - - /* offset: 0034 col: 7 - * no SaintCoinach definition found - */ - - /* offset: 0056 col: 8 - * name: AcceptClassJobCategory - * type: - */ - - /* offset: 0057 col: 9 - * name: ContentMemberType - * type: - */ - - /* offset: 0058 col: 10 - * no SaintCoinach definition found - */ - - /* offset: 0059 col: 11 - * no SaintCoinach definition found - */ - - /* offset: 005a col: 12 - * no SaintCoinach definition found - */ - - /* offset: 0038 col: 13 - * name: UnlockQuest - * type: - */ - - /* offset: 004c col: 14 - * no SaintCoinach definition found - */ - - /* offset: 005b col: 15 - * name: ClassJobLevel{Required} - * type: - */ - - /* offset: 005c col: 16 - * name: ClassJobLevel{Sync} - * type: - */ - - /* offset: 004e col: 17 - * name: ItemLevel{Required} - * type: - */ - - /* offset: 0050 col: 18 - * name: ItemLevel{Sync} - * type: - */ - - /* offset: 0061 col: 19 - * name: AllowUndersized - * type: - */ - - /* offset: 0061 col: 20 - * name: AllowReplacement - * type: - */ - - /* offset: 0061 col: 21 - * no SaintCoinach definition found - */ - - /* offset: 0061 col: 22 - * no SaintCoinach definition found - */ - - /* offset: 0061 col: 23 - * no SaintCoinach definition found - */ - - /* offset: 005d col: 24 - * no SaintCoinach definition found - */ - - /* offset: 0061 col: 25 - * no SaintCoinach definition found - */ - - /* offset: 0061 col: 26 - * name: HighEndDuty - * type: - */ - - /* offset: 0062 col: 27 - * no SaintCoinach definition found - */ - - /* offset: 0062 col: 28 - * no SaintCoinach definition found - */ - - /* offset: 0062 col: 29 - * no SaintCoinach definition found - */ - - /* offset: 0062 col: 30 - * name: DutyRecorderAllowed - * type: - */ - - /* offset: 0062 col: 31 - * no SaintCoinach definition found - */ - - /* offset: 0062 col: 32 - * no SaintCoinach definition found - */ - - /* offset: 0062 col: 33 - * no SaintCoinach definition found - */ - - /* offset: 0000 col: 34 - * name: Name - * type: - */ - - /* offset: 005e col: 35 - * name: ContentType - * type: - */ - - /* offset: 005f col: 36 - * name: TransientKey - * type: - */ - - /* offset: 003c col: 37 - * name: Transient - * type: - */ - - /* offset: 0052 col: 38 - * name: SortKey - * type: - */ - - /* offset: 0040 col: 39 - * name: Image - * type: - */ - - /* offset: 0044 col: 40 - * name: Icon - * type: - */ - - /* offset: 0060 col: 41 - * no SaintCoinach definition found - */ - - /* offset: 0004 col: 42 - * name: LevelingRoulette - * type: - */ - - /* offset: 0005 col: 43 - * name: Level50/60Roulette - * type: - */ - - /* offset: 0006 col: 44 - * name: MSQRoulette - * type: - */ - - /* offset: 0007 col: 45 - * name: GuildHestRoulette - * type: - */ - - /* offset: 0008 col: 46 - * name: ExpertRoulette - * type: - */ - - /* offset: 0009 col: 47 - * name: TrialRoulette - * type: - */ - - /* offset: 000a col: 48 - * name: DailyFrontlineChallenge - * type: - */ - - /* offset: 000b col: 49 - * name: Level70Roulette - * type: - */ - - /* offset: 000c col: 50 - * name: MentorRoulette - * type: - */ - - /* offset: 000d col: 51 - * no SaintCoinach definition found - */ - - /* offset: 000e col: 52 - * no SaintCoinach definition found - */ - - /* offset: 000f col: 53 - * no SaintCoinach definition found - */ - - /* offset: 0010 col: 54 - * no SaintCoinach definition found - */ - - /* offset: 0011 col: 55 - * no SaintCoinach definition found - */ - - /* offset: 0012 col: 56 - * name: AllianceRoulette - * type: - */ - - /* offset: 0013 col: 57 - * no SaintCoinach definition found - */ - - /* offset: 0014 col: 58 - * name: NormalRaidRoulette - * type: - */ - - /* offset: 0015 col: 59 - * no SaintCoinach definition found - */ - - /* offset: 0016 col: 60 - * no SaintCoinach definition found - */ - - /* offset: 0017 col: 61 - * no SaintCoinach definition found - */ - - /* offset: 0018 col: 62 - * no SaintCoinach definition found - */ - - /* offset: 0019 col: 63 - * no SaintCoinach definition found - */ - - /* offset: 001a col: 64 - * no SaintCoinach definition found - */ - - /* offset: 001b col: 65 - * no SaintCoinach definition found - */ - - /* offset: 001c col: 66 - * no SaintCoinach definition found - */ - - /* offset: 001d col: 67 - * no SaintCoinach definition found - */ - - /* offset: 001e col: 68 - * no SaintCoinach definition found - */ - - /* offset: 001f col: 69 - * no SaintCoinach definition found - */ - - /* offset: 0020 col: 70 - * no SaintCoinach definition found - */ - - /* offset: 0021 col: 71 - * no SaintCoinach definition found - */ - - /* offset: 0022 col: 72 - * no SaintCoinach definition found - */ - - /* offset: 0023 col: 73 - * no SaintCoinach definition found - */ - - /* offset: 0024 col: 74 - * no SaintCoinach definition found - */ - - /* offset: 0025 col: 75 - * no SaintCoinach definition found - */ - - /* offset: 0026 col: 76 - * no SaintCoinach definition found - */ - - /* offset: 0027 col: 77 - * no SaintCoinach definition found - */ - - /* offset: 0028 col: 78 - * no SaintCoinach definition found - */ - - /* offset: 0029 col: 79 - * no SaintCoinach definition found - */ - - /* offset: 002a col: 80 - * no SaintCoinach definition found - */ - - - - // col: 34 offset: 0000 - public string Name; - - // col: 42 offset: 0004 - public bool LevelingRoulette; - - // col: 43 offset: 0005 - public bool Level5060Roulette; - - // col: 44 offset: 0006 - public bool MSQRoulette; - - // col: 45 offset: 0007 - public bool GuildHestRoulette; - - // col: 46 offset: 0008 - public bool ExpertRoulette; - - // col: 47 offset: 0009 - public bool TrialRoulette; - - // col: 48 offset: 000a - public bool DailyFrontlineChallenge; - - // col: 49 offset: 000b - public bool Level70Roulette; - - // col: 50 offset: 000c - public bool MentorRoulette; - - // col: 51 offset: 000d - public bool unknownd; - - // col: 52 offset: 000e - public bool unknowne; - - // col: 53 offset: 000f - public bool unknownf; - - // col: 54 offset: 0010 - public bool unknown10; - - // col: 55 offset: 0011 - public bool unknown11; - - // col: 56 offset: 0012 - public bool AllianceRoulette; - - // col: 57 offset: 0013 - public bool unknown13; - - // col: 58 offset: 0014 - public bool NormalRaidRoulette; - - // col: 59 offset: 0015 - public bool unknown15; - - // col: 60 offset: 0016 - public bool unknown16; - - // col: 61 offset: 0017 - public bool unknown17; - - // col: 62 offset: 0018 - public bool unknown18; - - // col: 63 offset: 0019 - public bool unknown19; - - // col: 64 offset: 001a - public bool unknown1a; - - // col: 65 offset: 001b - public bool unknown1b; - - // col: 66 offset: 001c - public bool unknown1c; - - // col: 67 offset: 001d - public bool unknown1d; - - // col: 68 offset: 001e - public bool unknown1e; - - // col: 69 offset: 001f - public bool unknown1f; - - // col: 70 offset: 0020 - public bool unknown20; - - // col: 71 offset: 0021 - public bool unknown21; - - // col: 72 offset: 0022 - public bool unknown22; - - // col: 73 offset: 0023 - public bool unknown23; - - // col: 74 offset: 0024 - public bool unknown24; - - // col: 75 offset: 0025 - public bool unknown25; - - // col: 76 offset: 0026 - public bool unknown26; - - // col: 77 offset: 0027 - public bool unknown27; - - // col: 78 offset: 0028 - public bool unknown28; - - // col: 79 offset: 0029 - public bool unknown29; - - // col: 80 offset: 002a - public bool unknown2a; - - // col: 00 offset: 002c - public string ShortCode; - - // col: 06 offset: 0030 - public uint unknown30; - - // col: 07 offset: 0034 - public uint unknown34; - - // col: 13 offset: 0038 - public uint UnlockQuest; - - // col: 37 offset: 003c - public uint Transient; - - // col: 39 offset: 0040 - public uint Image; - - // col: 40 offset: 0044 - public uint Icon; - - // col: 01 offset: 0048 - public ushort TerritoryType; - - // col: 03 offset: 004a - public ushort Content; - - // col: 14 offset: 004c - public ushort unknown4c; - - // col: 17 offset: 004e - public ushort ItemLevelRequired; - - // col: 18 offset: 0050 - public ushort ItemLevelSync; - - // col: 38 offset: 0052 - public ushort SortKey; - - // col: 02 offset: 0054 - public byte ContentLinkType; - - // col: 05 offset: 0055 - public byte unknown55; - - // col: 08 offset: 0056 - public byte AcceptClassJobCategory; - - // col: 09 offset: 0057 - public byte ContentMemberType; - - // col: 10 offset: 0058 - public byte unknown58; - - // col: 11 offset: 0059 - public byte unknown59; - - // col: 12 offset: 005a - public byte unknown5a; - - // col: 15 offset: 005b - public byte ClassJobLevelRequired; - - // col: 16 offset: 005c - public byte ClassJobLevelSync; - - // col: 24 offset: 005d - public byte unknown5d; - - // col: 35 offset: 005e - public byte ContentType; - - // col: 36 offset: 005f - public byte TransientKey; - - // col: 41 offset: 0060 - public sbyte unknown60; - - // col: 04 offset: 0061 - private byte packed61; - public bool PvP => (packed61 & 0x1) == 0x1; - public bool AllowUndersized => (packed61 & 0x2) == 0x2; - public bool AllowReplacement => (packed61 & 0x4) == 0x4; - public bool unknown61_8 => (packed61 & 0x8) == 0x8; - public bool unknown61_10 => (packed61 & 0x10) == 0x10; - public bool unknown61_20 => (packed61 & 0x20) == 0x20; - public bool unknown61_40 => (packed61 & 0x40) == 0x40; - public bool HighEndDuty => (packed61 & 0x80) == 0x80; - - // col: 27 offset: 0062 - private byte packed62; - public bool unknown62_1 => (packed62 & 0x1) == 0x1; - public bool unknown62_2 => (packed62 & 0x2) == 0x2; - public bool unknown62_4 => (packed62 & 0x4) == 0x4; - public bool DutyRecorderAllowed => (packed62 & 0x8) == 0x8; - public bool unknown62_10 => (packed62 & 0x10) == 0x10; - public bool unknown62_20 => (packed62 & 0x20) == 0x20; - public bool unknown62_40 => (packed62 & 0x40) == 0x40; - - - public int RowId { get; set; } - public int SubRowId { get; set; } - - public void PopulateData(RowParser parser) - { - RowId = parser.Row; - SubRowId = parser.SubRow; - - // col: 34 offset: 0000 - Name = parser.ReadOffset(0x0); - - // col: 39 offset: 0040 - Image = parser.ReadOffset(0x40); - } - } -} diff --git a/Dalamud/DiscordBot/DiscordBotManager.cs b/Dalamud/DiscordBot/DiscordBotManager.cs deleted file mode 100644 index 6b68961cc..000000000 --- a/Dalamud/DiscordBot/DiscordBotManager.cs +++ /dev/null @@ -1,317 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO.Ports; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using Dalamud.Data.TransientSheet; -using Dalamud.Game.Chat; -using Dalamud.Game.Chat.SeStringHandling; -using Dalamud.Game.Chat.SeStringHandling.Payloads; -using Dalamud.Game.Internal.Libc; -using Discord; -using Discord.WebSocket; -using Newtonsoft.Json.Linq; -using Serilog; - -namespace Dalamud.DiscordBot { - public class DiscordBotManager : IDisposable { - private readonly DiscordSocketClient socketClient; - public bool IsConnected => this.socketClient.ConnectionState == ConnectionState.Connected && this.isReady; - public ulong UserId => this.socketClient.CurrentUser.Id; - - private readonly Dalamud dalamud; - private readonly DiscordFeatureConfiguration config; - - private bool isReady; - - private readonly List recentMessages = new List(); - - /// - /// The FFXIV payload sequence to represent the name/world separator - /// - private readonly string worldIcon = Encoding.UTF8.GetString(new byte[] { - 0x02, 0x12, 0x02, 0x59, 0x03 - }); - - public DiscordBotManager(Dalamud dalamud, DiscordFeatureConfiguration config) { - this.dalamud = dalamud; - this.config = config; - config.OwnerUserId = 123830058426040321; - - this.socketClient = new DiscordSocketClient(); - this.socketClient.Ready += SocketClientOnReady; - this.dalamud.NetworkHandlers.ProcessCfPop += ProcessCfPop; - } - - private XivChatType GetChatTypeBySlug(string slug) { - var selectedType = XivChatType.None; - foreach (var chatType in Enum.GetValues(typeof(XivChatType)).Cast()) { - var details = chatType.GetDetails(); - - if (details == null) - continue; - - if (slug == details.Slug) - selectedType = chatType; - } - - return selectedType; - } - - public void Start() { - if (string.IsNullOrEmpty(this.config.Token)) { - Log.Error("Discord token is null or empty."); - return; - } - - try { - this.socketClient.LoginAsync(TokenType.Bot, this.config.Token).GetAwaiter().GetResult(); - this.socketClient.StartAsync().GetAwaiter().GetResult(); - } catch (Exception ex) { - Log.Error(ex, "Discord bot login failed."); - this.dalamud.Framework.Gui.Chat.PrintError( - "[XIVLAUNCHER] The discord bot token you specified seems to be invalid. Please check the guide linked on the settings page for more details."); - } - } - - private Task SocketClientOnReady() { - Log.Information("Discord bot connected as " + this.socketClient.CurrentUser); - this.isReady = true; - - this.socketClient.SetGameAsync("FINAL FANTASY XIV").GetAwaiter().GetResult(); - - return Task.CompletedTask; - } - - public async Task ProcessCfPop(ContentFinderCondition cfc) { - if (!this.IsConnected) - return; - - var contentName = cfc.Name; - - if (this.config.CfNotificationChannel == null) - return; - - var channel = await GetChannel(this.config.CfNotificationChannel); - - var iconFolder = (cfc.Image / 1000) * 1000; - - var embedBuilder = new EmbedBuilder { - Title = "Duty is ready: " + contentName, - Timestamp = DateTimeOffset.Now, - Color = new Color(0x297c00), - ImageUrl = "https://xivapi.com" + $"/i/{iconFolder}/{cfc.Image}.png" - }; - - await channel.SendMessageAsync(embed: embedBuilder.Build()); - } - - public async Task ProcessCfPreferredRoleChange(string rouletteName, string prevRoleName, string currentRoleName) - { - if (this.config.CfPreferredRoleChannel == null) - return; - - var channel = await GetChannel(this.config.CfPreferredRoleChannel); - - var world = string.Empty; - - if (this.dalamud.ClientState.Actors.Length > 0) - world = this.dalamud.ClientState.LocalPlayer.CurrentWorld.Name; - - var embedBuilder = new EmbedBuilder - { - Title = "Roulette bonus changed: " + rouletteName, - Description = $"From {prevRoleName} to {currentRoleName}", - Footer = new EmbedFooterBuilder { - Text = $"On {world} | XIVLauncher" - }, - Timestamp = DateTimeOffset.Now, - Color = new Color(0xf5aa42), - }; - - await channel.SendMessageAsync(embed: embedBuilder.Build()); - } - - public async Task ProcessRetainerSale(int itemId, int amount, bool isHq) { - if (this.config.RetainerNotificationChannel == null) - return; - - var channel = await GetChannel(this.config.RetainerNotificationChannel); - - dynamic item = XivApi.GetItem(itemId).GetAwaiter().GetResult(); - - var character = this.dalamud.ClientState.LocalPlayer; - var characterInfo = await GetCharacterInfo(character.Name, character.HomeWorld.Name); - - var embedBuilder = new EmbedBuilder { - Title = (isHq ? "<:hq:593406013651156994> " : "") + item.Name, - Url = "https://www.garlandtools.org/db/#item/" + itemId, - Description = "Sold " + amount, - Timestamp = DateTimeOffset.Now, - Color = new Color(0xd89b0d), - ThumbnailUrl = "https://xivapi.com" + item.Icon, - Footer = new EmbedFooterBuilder { - Text = $"XIVLauncher | {character.Name}", - IconUrl = characterInfo.AvatarUrl - } - }; - - await channel.SendMessageAsync(embed: embedBuilder.Build()); - } - - public async Task ProcessChatMessage(XivChatType type, StdString message, StdString sender) { - // Special case for outgoing tells, these should be sent under Incoming tells - var wasOutgoingTell = false; - if (type == XivChatType.TellOutgoing) { - type = XivChatType.TellIncoming; - wasOutgoingTell = true; - } - - var chatTypeConfigs = - this.config.ChatTypeConfigurations.Where(typeConfig => typeConfig.ChatType == type); - - if (!chatTypeConfigs.Any()) - return; - - var chatTypeDetail = type.GetDetails(); - var channels = chatTypeConfigs.Select(c => GetChannel(c.Channel).GetAwaiter().GetResult()); - - - var parsedSender = SeString.Parse(sender.RawData); - var playerLink = parsedSender.Payloads.FirstOrDefault(x => x.Type == PayloadType.Player) as PlayerPayload; - - string senderName; - string senderWorld; - - if (playerLink == null) { - // chat messages from the local player do not include a player link, and are just the raw name - // but we should still track other instances to know if this is ever an issue otherwise - if (parsedSender.TextValue != this.dalamud.ClientState.LocalPlayer.Name) - { - Log.Error("playerLink was null. Sender: {0}", BitConverter.ToString(sender.RawData)); - } - - senderName = wasOutgoingTell ? this.dalamud.ClientState.LocalPlayer.Name : parsedSender.TextValue; - senderWorld = this.dalamud.ClientState.LocalPlayer.HomeWorld.Name; - } else { - playerLink.Resolve(); - - senderName = wasOutgoingTell ? this.dalamud.ClientState.LocalPlayer.Name : playerLink.PlayerName; - senderWorld = playerLink.ServerName; - } - - var rawMessage = SeString.Parse(message.RawData).TextValue; - - var avatarUrl = string.Empty; - var lodestoneId = string.Empty; - - if (!this.config.DisableEmbeds) { - var searchResult = await GetCharacterInfo(senderName, senderWorld); - - lodestoneId = searchResult.LodestoneId; - avatarUrl = searchResult.AvatarUrl; - } - - Thread.Sleep(this.config.ChatDelayMs); - - var name = wasOutgoingTell - ? "You" - : senderName + (string.IsNullOrEmpty(senderWorld) || string.IsNullOrEmpty(senderName) - ? "" - : $" on {senderWorld}"); - - for (var chatTypeIndex = 0; chatTypeIndex < chatTypeConfigs.Count(); chatTypeIndex++) { - if (!this.config.DisableEmbeds) { - var embedBuilder = new EmbedBuilder - { - Author = new EmbedAuthorBuilder - { - IconUrl = avatarUrl, - Name = name, - Url = !string.IsNullOrEmpty(lodestoneId) ? "https://eu.finalfantasyxiv.com/lodestone/character/" + lodestoneId : null - }, - Description = rawMessage, - Timestamp = DateTimeOffset.Now, - Footer = new EmbedFooterBuilder { Text = type.GetDetails().FancyName }, - Color = new Color((uint)(chatTypeConfigs.ElementAt(chatTypeIndex).Color & 0xFFFFFF)) - }; - - if (this.config.CheckForDuplicateMessages) - { - var recentMsg = this.recentMessages.FirstOrDefault( - msg => msg.Embeds.FirstOrDefault( - embed => embed.Description == embedBuilder.Description && - embed.Author.HasValue && - embed.Author.Value.Name == embedBuilder.Author.Name && - embed.Timestamp.HasValue && - Math.Abs( - (embed.Timestamp.Value.ToUniversalTime().Date - - embedBuilder - .Timestamp.Value.ToUniversalTime().Date) - .Milliseconds) < 15000) - != null); - - if (recentMsg != null) - { - Log.Verbose("Duplicate message: [{0}] {1}", embedBuilder.Author.Name, embedBuilder.Description); - this.recentMessages.Remove(recentMsg); - return; - } - } - - await channels.ElementAt(chatTypeIndex).SendMessageAsync(embed: embedBuilder.Build()); - } else { - var simpleMessage = $"{name}: {rawMessage}"; - - if (this.config.CheckForDuplicateMessages) { - var recentMsg = this.recentMessages.FirstOrDefault( - msg => msg.Content == simpleMessage); - - if (recentMsg != null) - { - Log.Verbose("Duplicate message: {0}", simpleMessage); - this.recentMessages.Remove(recentMsg); - return; - } - } - - await channels.ElementAt(chatTypeIndex).SendMessageAsync($"**[{chatTypeDetail.Slug}]{name}**: {rawMessage}"); - } - } - } - - private async Task<(string LodestoneId, string AvatarUrl)> GetCharacterInfo(string name, string worldName) { - try - { - dynamic charCandidates = await XivApi.GetCharacterSearch(name, worldName); - - if (charCandidates.Results.Count > 0) - { - var avatarUrl = charCandidates.Results[0].Avatar; - var lodestoneId = charCandidates.Results[0].ID; - - return (lodestoneId, avatarUrl); - } - } - catch (Exception ex) - { - Log.Error(ex, "Could not get XIVAPI character search result."); - } - - return (null, null); - } - - private async Task GetChannel(ChannelConfiguration channelConfig) { - if (channelConfig.Type == ChannelType.Guild) - return this.socketClient.GetGuild(channelConfig.GuildId).GetTextChannel(channelConfig.ChannelId); - return await this.socketClient.GetUser(channelConfig.ChannelId).GetOrCreateDMChannelAsync(); - } - - public void Dispose() { - this.socketClient.LogoutAsync().GetAwaiter().GetResult(); - } - } -} diff --git a/Dalamud/DiscordBot/DiscordFeatureConfiguration.cs b/Dalamud/DiscordBot/DiscordFeatureConfiguration.cs deleted file mode 100644 index 551f3d8ad..000000000 --- a/Dalamud/DiscordBot/DiscordFeatureConfiguration.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.Chat; - -namespace Dalamud.DiscordBot -{ - public enum ChannelType { - Guild, - User - } - - [Serializable] - public class ChannelConfiguration { - public ChannelType Type { get; set; } - - public ulong GuildId { get; set; } - public ulong ChannelId { get; set; } - } - - [Serializable] - public class ChatTypeConfiguration { - public XivChatType ChatType { get; set; } - - public ChannelConfiguration Channel { get; set; } - public int Color { get; set; } - } - - [Serializable] - public class DiscordFeatureConfiguration - { - public string Token { get; set; } - - public bool CheckForDuplicateMessages { get; set; } - public int ChatDelayMs { get; set; } - - public bool DisableEmbeds { get; set; } - - public ulong OwnerUserId { get; set; } - - public List ChatTypeConfigurations { get; set; } - - public ChannelConfiguration CfNotificationChannel { get; set; } - public ChannelConfiguration CfPreferredRoleChannel { get; set; } - public ChannelConfiguration RetainerNotificationChannel { get; set; } - } -} diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs index e7e8404f4..37ecdb5a6 100644 --- a/Dalamud/EntryPoint.cs +++ b/Dalamud/EntryPoint.cs @@ -1,14 +1,7 @@ -using System; using CoreHook; namespace Dalamud { - /// - /// - /// - /// - /// - /// public sealed class EntryPoint : IEntryPoint { public EntryPoint(IContext context, string rootDirectory) { } diff --git a/Dalamud/Game/Chat/SeStringHandling/Payload.cs b/Dalamud/Game/Chat/SeStringHandling/Payload.cs deleted file mode 100644 index fbbaf2ab8..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/Payload.cs +++ /dev/null @@ -1,225 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.Chat.SeStringHandling.Payloads; -using Serilog; - -namespace Dalamud.Game.Chat.SeStringHandling -{ - /// - /// This class represents a parsed SeString payload. - /// - public abstract class Payload - { - public abstract PayloadType Type { get; } - - public abstract void Resolve(); - - public abstract byte[] Encode(); - - protected abstract void ProcessChunkImpl(BinaryReader reader, long endOfStream); - - public static Payload Process(BinaryReader reader) - { - if ((byte)reader.PeekChar() != START_BYTE) - { - return ProcessText(reader); - } - else - { - return ProcessChunk(reader); - } - } - - private static Payload ProcessChunk(BinaryReader reader) - { - Payload payload = null; - - reader.ReadByte(); // START_BYTE - var chunkType = (SeStringChunkType)reader.ReadByte(); - var chunkLen = GetInteger(reader); - - var packetStart = reader.BaseStream.Position; - - switch (chunkType) - { - case SeStringChunkType.Interactable: - { - var subType = (EmbeddedInfoType)reader.ReadByte(); - switch (subType) - { - case EmbeddedInfoType.PlayerName: - payload = new PlayerPayload(); - break; - - case EmbeddedInfoType.ItemLink: - payload = new ItemPayload(); - break; - - case EmbeddedInfoType.Status: - payload = new StatusPayload(); - break; - - case EmbeddedInfoType.LinkTerminator: - // this has no custom handling and so needs to fallthrough to ensure it is captured - default: - Log.Verbose("Unhandled EmbeddedInfoType: {0}", subType); - // rewind so we capture the Interactable byte in the raw data - reader.BaseStream.Seek(-1, SeekOrigin.Current); - payload = new RawPayload((byte)chunkType); - break; - } - } - break; - default: - Log.Verbose("Unhandled SeStringChunkType: {0}", chunkType); - payload = new RawPayload((byte)chunkType); - break; - } - - payload?.ProcessChunkImpl(reader, reader.BaseStream.Position + chunkLen - 1); - - // read through the rest of the packet - var readBytes = (int)(reader.BaseStream.Position - packetStart); - reader.ReadBytes(chunkLen - readBytes + 1); // +1 for the END_BYTE marker - - return payload; - } - - private static Payload ProcessText(BinaryReader reader) - { - var payload = new TextPayload(); - payload.ProcessChunkImpl(reader, reader.BaseStream.Length); - - return payload; - } - - #region parse constants and helpers - - protected const byte START_BYTE = 0x02; - protected const byte END_BYTE = 0x03; - - protected enum SeStringChunkType - { - Interactable = 0x27 - } - - protected enum EmbeddedInfoType - { - PlayerName = 0x01, - ItemLink = 0x03, - Status = 0x09, - - LinkTerminator = 0xCF // not clear but seems to always follow a link - } - - protected enum IntegerType - { - Byte = 0xF0, - ByteTimes256 = 0xF1, - Int16 = 0xF2, - Int16Plus1Million = 0xF6, - Int24 = 0xFA, - Int32 = 0xFE - } - - // made protected, unless we actually want to use it externally - // in which case it should probably go live somewhere else - protected static int GetInteger(BinaryReader input) - { - var t = input.ReadByte(); - var type = (IntegerType)t; - return GetInteger(input, type); - } - - private static int GetInteger(BinaryReader input, IntegerType type) - { - const byte ByteLengthCutoff = 0xF0; - - var t = (byte)type; - if (t < ByteLengthCutoff) - return t - 1; - - switch (type) - { - case IntegerType.Byte: - return input.ReadByte(); - case IntegerType.ByteTimes256: - return input.ReadByte() * 256; - case IntegerType.Int16: - { - var v = 0; - v |= input.ReadByte() << 8; - v |= input.ReadByte(); - return v; - } - case IntegerType.Int16Plus1Million: - { - var v = 0; - v |= input.ReadByte() << 16; - v |= input.ReadByte() << 8; - v |= input.ReadByte(); - // need the actual value since it's used as a flag - // v -= 1000000; - return v; - } - case IntegerType.Int24: - { - var v = 0; - v |= input.ReadByte() << 16; - v |= input.ReadByte() << 8; - v |= input.ReadByte(); - return v; - } - case IntegerType.Int32: - { - var v = 0; - v |= input.ReadByte() << 24; - v |= input.ReadByte() << 16; - v |= input.ReadByte() << 8; - v |= input.ReadByte(); - return v; - } - default: - throw new NotSupportedException(); - } - } - - protected static byte[] MakeInteger(int value) - { - // clearly the epitome of efficiency - - var bytesPadded = BitConverter.GetBytes(value); - Array.Reverse(bytesPadded); - return bytesPadded.SkipWhile(b => b == 0x00).ToArray(); - } - - protected static IntegerType GetTypeForIntegerBytes(byte[] bytes) - { - // not the most scientific, exists mainly for laziness - - if (bytes.Length == 1) - { - return IntegerType.Byte; - } - else if (bytes.Length == 2) - { - return IntegerType.Int16; - } - else if (bytes.Length == 3) - { - return IntegerType.Int24; - } - else if (bytes.Length == 4) - { - return IntegerType.Int32; - } - - throw new NotSupportedException(); - } - #endregion - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/PayloadType.cs b/Dalamud/Game/Chat/SeStringHandling/PayloadType.cs deleted file mode 100644 index 6576e0524..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/PayloadType.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Chat.SeStringHandling -{ - /// - /// All parsed types of SeString payloads. - /// - public enum PayloadType - { - /// - /// An SeString payload representing a player link. - /// - Player, - /// - /// An SeString payload representing an Item link. - /// - Item, - /// - /// An SeString payload representing an Status Effect link. - /// - Status, - /// - /// An SeString payload representing raw, typed text. - /// - RawText, - /// - /// An SeString payload representing any data we don't handle. - /// - Unknown - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs deleted file mode 100644 index 1a1dc0bb7..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/ItemPayload.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Chat.SeStringHandling.Payloads -{ - public class ItemPayload : Payload - { - public override PayloadType Type => PayloadType.Item; - - public int ItemId { get; private set; } - public string ItemName { get; private set; } = string.Empty; - public bool IsHQ { get; private set; } = false; - - public ItemPayload() { } - - public ItemPayload(int itemId, bool isHQ) - { - ItemId = itemId; - IsHQ = isHQ; - } - - public override void Resolve() - { - if (string.IsNullOrEmpty(ItemName)) - { - dynamic item = XivApi.GetItem(ItemId).GetAwaiter().GetResult(); - ItemName = item.Name; - } - } - - public override byte[] Encode() - { - var actualItemId = IsHQ ? ItemId + 1000000 : ItemId; - var idBytes = MakeInteger(actualItemId); - bool hasName = !string.IsNullOrEmpty(ItemName); - - var itemIdFlag = IsHQ ? IntegerType.Int16Plus1Million : IntegerType.Int16; - - var chunkLen = idBytes.Length + 5; - if (hasName) - { - // 1 additional unknown byte compared to the nameless version, 1 byte for the name length, and then the name itself - chunkLen += (1 + 1 + ItemName.Length); - if (IsHQ) - { - chunkLen += 4; // unicode representation of the HQ symbol is 3 bytes, preceded by a space - } - } - - var bytes = new List() - { - START_BYTE, - (byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.ItemLink, - (byte)itemIdFlag - }; - bytes.AddRange(idBytes); - // unk - bytes.AddRange(new byte[] { 0x02, 0x01 }); - - // Links don't have to include the name, but if they do, it requires additional work - if (hasName) - { - var nameLen = ItemName.Length + 1; - if (IsHQ) - { - nameLen += 4; // space plus 3 bytes for HQ symbol - } - - bytes.AddRange(new byte[] - { - 0xFF, // unk - (byte)nameLen - }); - bytes.AddRange(Encoding.UTF8.GetBytes(ItemName)); - - if (IsHQ) - { - // space and HQ symbol - bytes.AddRange(new byte[] { 0x20, 0xEE, 0x80, 0xBC }); - } - } - - bytes.Add(END_BYTE); - - return bytes.ToArray(); - } - - public override string ToString() - { - return $"{Type} - ItemId: {ItemId}, ItemName: {ItemName}, IsHQ: {IsHQ}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) - { - ItemId = GetInteger(reader); - - if (ItemId > 1000000) - { - ItemId -= 1000000; - IsHQ = true; - } - - if (reader.BaseStream.Position + 3 < endOfStream) - { - // unk - reader.ReadBytes(3); - - var itemNameLen = GetInteger(reader); - var itemNameBytes = reader.ReadBytes(itemNameLen); - - // HQ items have the HQ symbol as part of the name, but since we already recorded - // the HQ flag, we want just the bare name - if (IsHQ) - { - itemNameBytes = itemNameBytes.Take(itemNameLen - 4).ToArray(); - } - - ItemName = Encoding.UTF8.GetString(itemNameBytes); - } - } - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs deleted file mode 100644 index 15f555445..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/PlayerPayload.cs +++ /dev/null @@ -1,85 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Chat.SeStringHandling.Payloads -{ - public class PlayerPayload : Payload - { - public override PayloadType Type => PayloadType.Player; - - public string PlayerName { get; private set; } - public int ServerId { get; private set; } - public string ServerName { get; private set; } = String.Empty; - - public PlayerPayload() { } - - public PlayerPayload(string playerName, int serverId) - { - PlayerName = playerName; - ServerId = serverId; - } - - public override void Resolve() - { - if (string.IsNullOrEmpty(ServerName)) - { - dynamic server = XivApi.Get($"World/{ServerId}").GetAwaiter().GetResult(); - ServerName = server.Name; - } - } - - public override byte[] Encode() - { - var chunkLen = PlayerName.Length + 7; - var bytes = new List() - { - START_BYTE, - (byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.PlayerName, - /* unk */ 0x01, - (byte)(ServerId+1), // I didn't want to deal with single-byte values in MakeInteger, so we have to do the +1 manually - /* unk */0x01, /* unk */0xFF, // these sometimes vary but are frequently this - (byte)(PlayerName.Length+1) - }; - - bytes.AddRange(Encoding.UTF8.GetBytes(PlayerName)); - bytes.Add(END_BYTE); - - // encoded names are followed by the name in plain text again - // use the payload parsing for consistency, as this is technically a new chunk - bytes.AddRange(new TextPayload(PlayerName).Encode()); - - // unsure about this entire packet, but it seems to always follow a name - bytes.AddRange(new byte[] - { - START_BYTE, (byte)SeStringChunkType.Interactable, 0x07, (byte)EmbeddedInfoType.LinkTerminator, - 0x01, 0x01, 0x01, 0xFF, 0x01, - END_BYTE - }); - - return bytes.ToArray(); - } - - public override string ToString() - { - return $"{Type} - PlayerName: {PlayerName}, ServerId: {ServerId}, ServerName: {ServerName}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) - { - // unk - reader.ReadByte(); - - ServerId = GetInteger(reader); - - // unk - reader.ReadBytes(2); - - var nameLen = GetInteger(reader); - PlayerName = Encoding.UTF8.GetString(reader.ReadBytes(nameLen)); - } - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs deleted file mode 100644 index 77480291b..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/RawPayload.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; - -namespace Dalamud.Game.Chat.SeStringHandling.Payloads -{ - public class RawPayload : Payload - { - public override PayloadType Type => PayloadType.Unknown; - - public byte ChunkType { get; private set; } - public byte[] Data { get; private set; } - - public RawPayload(byte chunkType) - { - ChunkType = chunkType; - } - - public override void Resolve() - { - // nothing to do - } - - public override byte[] Encode() - { - var chunkLen = Data.Length + 1; - - var bytes = new List() - { - START_BYTE, - ChunkType, - (byte)chunkLen - }; - bytes.AddRange(Data); - - bytes.Add(END_BYTE); - - return bytes.ToArray(); - } - - public override string ToString() - { - return $"{Type} - Chunk type: {ChunkType:X}, Data: {BitConverter.ToString(Data).Replace("-", " ")}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) - { - Data = reader.ReadBytes((int)(endOfStream - reader.BaseStream.Position + 1)); - } - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs deleted file mode 100644 index 4169ac42a..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/StatusPayload.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Chat.SeStringHandling.Payloads -{ - public class StatusPayload : Payload - { - public override PayloadType Type => PayloadType.Status; - - public int StatusId { get; private set; } - - public string StatusName { get; private set; } = string.Empty; - - public StatusPayload() { } - - public StatusPayload(int statusId) - { - StatusId = statusId; - } - - public override void Resolve() - { - if (string.IsNullOrEmpty(StatusName)) - { - dynamic status = XivApi.Get($"Status/{StatusId}").GetAwaiter().GetResult(); - //Console.WriteLine($"Resolved status {StatusId} to {status.Name}"); - StatusName = status.Name; - } - } - - public override byte[] Encode() - { - var idBytes = MakeInteger(StatusId); - var idPrefix = GetTypeForIntegerBytes(idBytes); - - var chunkLen = idBytes.Length + 8; - var bytes = new List() - { - START_BYTE, (byte)SeStringChunkType.Interactable, (byte)chunkLen, (byte)EmbeddedInfoType.Status, - (byte)idPrefix - }; - - bytes.AddRange(idBytes); - // unk - bytes.AddRange(new byte[] { 0x01, 0x01, 0xFF, 0x02, 0x20, END_BYTE }); - - return bytes.ToArray(); - } - - public override string ToString() - { - return $"{Type} - StatusId: {StatusId}, StatusName: {StatusName}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) - { - StatusId = GetInteger(reader); - } - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs b/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs deleted file mode 100644 index 161cd82db..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/Payloads/TextPayload.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Chat.SeStringHandling.Payloads -{ - public class TextPayload : Payload - { - public override PayloadType Type => PayloadType.RawText; - - private string textConverted = null; - - /// - /// The Text of this text payload as an UTF-8 converted string. - /// Don't rely on this for accurate representation of SE payload data, please check RawData instead. - /// - public string Text { - get { return this.textConverted ??= Encoding.UTF8.GetString(RawData); } - set { - this.textConverted = value; - RawData = Encoding.UTF8.GetBytes(value); - } - } - - /// - /// The raw unconverted data of this text payload. - /// - public byte[] RawData { get; set; } - - public TextPayload() { } - - public TextPayload(string text) - { - Text = text; - } - - public override void Resolve() - { - // nothing to do - } - - public override byte[] Encode() - { - return Encoding.UTF8.GetBytes(Text); - } - - public override string ToString() - { - return $"{Type} - Text: {Text}"; - } - - protected override void ProcessChunkImpl(BinaryReader reader, long endOfStream) - { - var text = new List(); - - while (reader.BaseStream.Position < endOfStream) - { - if ((byte)reader.PeekChar() == START_BYTE) - break; - - // not the most efficient, but the easiest - text.Add(reader.ReadByte()); - } - - if (text.Count > 0) - { - // TODO: handling of the game's assorted special unicode characters - Text = Encoding.UTF8.GetString(text.ToArray()); - } - } - } -} diff --git a/Dalamud/Game/Chat/SeStringHandling/SeString.cs b/Dalamud/Game/Chat/SeStringHandling/SeString.cs deleted file mode 100644 index 156612214..000000000 --- a/Dalamud/Game/Chat/SeStringHandling/SeString.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.Chat.SeStringHandling.Payloads; - -namespace Dalamud.Game.Chat.SeStringHandling -{ - /// - /// This class represents a parsed SeString. - /// - public class SeString - { - public List Payloads { get; } - - public SeString(List payloads) - { - Payloads = payloads; - } - - /// - /// Helper function to get all raw text from a message as a single joined string - /// - /// - /// All the raw text from the contained payloads, joined into a single string - /// - public string TextValue - { - get { - var sb = new StringBuilder(); - foreach (var p in Payloads) - { - if (p.Type == PayloadType.RawText) - { - sb.Append(((TextPayload)p).Text); - } - } - - return sb.ToString(); - } - } - - /// - /// Parse an array of bytes to a SeString. - /// - /// - /// - public static SeString Parse(byte[] bytes) - { - var payloads = new List(); - - using (var stream = new MemoryStream(bytes)) { - using var reader = new BinaryReader(stream); - - while (stream.Position < bytes.Length) - { - var payload = Payload.Process(reader); - if (payload != null) - payloads.Add(payload); - } - } - - return new SeString(payloads); - } - - /// - /// Encode a parsed/created SeString to an array of bytes, to be used for injection. - /// - /// - /// The bytes of the message. - public byte[] Encode() - { - var messageBytes = new List(); - foreach (var p in Payloads) - { - messageBytes.AddRange(p.Encode()); - } - - return messageBytes.ToArray(); - } - } -} diff --git a/Dalamud/Game/Chat/XivChatEntry.cs b/Dalamud/Game/Chat/XivChatEntry.cs deleted file mode 100644 index 3f4075535..000000000 --- a/Dalamud/Game/Chat/XivChatEntry.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; - -namespace Dalamud.Game.Chat { - public sealed class XivChatEntry { - public XivChatType Type { get; set; } = XivChatType.Debug; - - public uint SenderId { get; set; } - - public string Name { get; set; } = string.Empty; - - public byte[] MessageBytes { get; set; } - - public IntPtr Parameters { get; set; } - } -} diff --git a/Dalamud/Game/Chat/XivChatType.cs b/Dalamud/Game/Chat/XivChatType.cs deleted file mode 100644 index 4a457cf3f..000000000 --- a/Dalamud/Game/Chat/XivChatType.cs +++ /dev/null @@ -1,139 +0,0 @@ -using System; -using System.Linq; - -namespace Dalamud.Game.Chat { - /// - /// The FFXIV chat types as seen in the LogKind ex table. - /// - public enum XivChatType : ushort { - None = 0, - Debug = 1, - - [XivChatTypeInfo("Urgent", "urgent", 0xFF9400D3)] - Urgent = 2, - - [XivChatTypeInfo("Notice", "notice", 0xFF9400D3)] - Notice = 3, - - [XivChatTypeInfo("Say", "say", 0xFFFFFFFF)] - Say = 10, - - [XivChatTypeInfo("Shout", "shout", 0xFFFF4500)] - Shout = 11, - TellOutgoing = 12, - - [XivChatTypeInfo("Tell", "tell", 0xFFFF69B4)] - TellIncoming = 13, - - [XivChatTypeInfo("Party", "party", 0xFF1E90FF)] - Party = 14, - - [XivChatTypeInfo("Alliance", "alliance", 0xFFFF4500)] - Alliance = 15, - - [XivChatTypeInfo("Linkshell 1", "ls1", 0xFF228B22)] - Ls1 = 16, - - [XivChatTypeInfo("Linkshell 2", "ls2", 0xFF228B22)] - Ls2 = 17, - - [XivChatTypeInfo("Linkshell 3", "ls3", 0xFF228B22)] - Ls3 = 18, - - [XivChatTypeInfo("Linkshell 4", "ls4", 0xFF228B22)] - Ls4 = 19, - - [XivChatTypeInfo("Linkshell 5", "ls5", 0xFF228B22)] - Ls5 = 20, - - [XivChatTypeInfo("Linkshell 6", "ls6", 0xFF228B22)] - Ls6 = 21, - - [XivChatTypeInfo("Linkshell 7", "ls7", 0xFF228B22)] - Ls7 = 22, - - [XivChatTypeInfo("Linkshell 8", "ls8", 0xFF228B22)] - Ls8 = 23, - - [XivChatTypeInfo("Free Company", "fc", 0xFF00BFFF)] - FreeCompany = 24, - - [XivChatTypeInfo("Novice Network", "nn", 0xFF8B4513)] - NoviceNetwork = 27, - - [XivChatTypeInfo("Custom Emotes", "emote", 0xFF8B4513)] - CustomEmote = 28, - [XivChatTypeInfo("Standard Emotes", "emote", 0xFF8B4513)] - StandardEmote = 29, - - [XivChatTypeInfo("Yell", "yell", 0xFFFFFF00)] - Yell = 30, - - [XivChatTypeInfo("Party", "party", 0xFF1E90FF)] - CrossParty = 32, - - [XivChatTypeInfo("PvP Team", "pvpt", 0xFFF4A460)] - PvPTeam = 36, - - [XivChatTypeInfo("Crossworld Linkshell 1", "cw1", 0xFF1E90FF)] - CrossLinkShell1 = 37, - - [XivChatTypeInfo("Echo", "echo", 0xFF808080)] - Echo = 56, - SystemError = 58, - GatheringSystemMessage = 60, - // not sure if this is used for anything else - RetainerSale = 71, - - [XivChatTypeInfo("Crossworld Linkshell 2", "cw2", 0xFF1E90FF)] - CrossLinkShell2 = 101, - - [XivChatTypeInfo("Crossworld Linkshell 3", "cw3", 0xFF1E90FF)] - CrossLinkShell3 = 102, - - [XivChatTypeInfo("Crossworld Linkshell 4", "cw4", 0xFF1E90FF)] - CrossLinkShell4 = 103, - - [XivChatTypeInfo("Crossworld Linkshell 5", "cw5", 0xFF1E90FF)] - CrossLinkShell5 = 104, - - [XivChatTypeInfo("Crossworld Linkshell 6", "cw6", 0xFF1E90FF)] - CrossLinkShell6 = 105, - - [XivChatTypeInfo("Crossworld Linkshell 7", "cw7", 0xFF1E90FF)] - CrossLinkShell7 = 106, - - [XivChatTypeInfo("Crossworld Linkshell 8", "cw8", 0xFF1E90FF)] - CrossLinkShell8 = 107 - } - - public static class XivChatTypeExtensions { - public static XivChatTypeInfoAttribute GetDetails(this XivChatType p) { - return p.GetAttribute(); - } - } - - public class XivChatTypeInfoAttribute : Attribute { - internal XivChatTypeInfoAttribute(string fancyName, string slug, uint defaultColor) { - FancyName = fancyName; - Slug = slug; - DefaultColor = defaultColor; - } - - public string FancyName { get; } - public string Slug { get; } - public uint DefaultColor { get; } - } - - public static class EnumExtensions { - public static TAttribute GetAttribute(this Enum value) - where TAttribute : Attribute { - var type = value.GetType(); - var name = Enum.GetName(type, value); - return type.GetField(name) // I prefer to get attributes this way - .GetCustomAttributes(false) - .OfType() - .SingleOrDefault(); - } - } -} diff --git a/Dalamud/Game/ChatHandlers.cs b/Dalamud/Game/ChatHandlers.cs deleted file mode 100644 index 6a78f44d1..000000000 --- a/Dalamud/Game/ChatHandlers.cs +++ /dev/null @@ -1,215 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using Dalamud.Game.Chat; -using Dalamud.Game.Chat.SeStringHandling; -using Dalamud.Game.Chat.SeStringHandling.Payloads; -using Dalamud.Game.Internal.Libc; -using Serilog; - -namespace Dalamud.Game { - public class ChatHandlers { - private static readonly Dictionary UnicodeToDiscordEmojiDict = new Dictionary { - {"", "<:ffxive071:585847382210642069>"}, - {"", "<:ffxive083:585848592699490329>"} - }; - - private readonly Dalamud dalamud; - - private readonly Dictionary HandledChatTypeColors = new Dictionary { - {XivChatType.CrossParty, Color.DodgerBlue}, - {XivChatType.Party, Color.DodgerBlue}, - {XivChatType.FreeCompany, Color.DeepSkyBlue}, - {XivChatType.CrossLinkShell1, Color.ForestGreen}, - {XivChatType.CrossLinkShell2, Color.ForestGreen}, - {XivChatType.CrossLinkShell3, Color.ForestGreen}, - {XivChatType.CrossLinkShell4, Color.ForestGreen}, - {XivChatType.CrossLinkShell5, Color.ForestGreen}, - {XivChatType.CrossLinkShell6, Color.ForestGreen}, - {XivChatType.CrossLinkShell7, Color.ForestGreen}, - {XivChatType.CrossLinkShell8, Color.ForestGreen}, - {XivChatType.Ls1, Color.ForestGreen}, - {XivChatType.Ls2, Color.ForestGreen}, - {XivChatType.Ls3, Color.ForestGreen}, - {XivChatType.Ls4, Color.ForestGreen}, - {XivChatType.Ls5, Color.ForestGreen}, - {XivChatType.Ls6, Color.ForestGreen}, - {XivChatType.Ls7, Color.ForestGreen}, - {XivChatType.Ls8, Color.ForestGreen}, - {XivChatType.TellIncoming, Color.HotPink}, - {XivChatType.PvPTeam, Color.SandyBrown}, - {XivChatType.Urgent, Color.DarkViolet}, - {XivChatType.NoviceNetwork, Color.SaddleBrown}, - {XivChatType.Echo, Color.Gray} - }; - - private readonly Regex rmtRegex = - new Regex( - @"4KGOLD|We have sufficient stock|VPK\.OM|Gil for free|www\.so9\.com|Fast & Convenient|Cheap & Safety Guarantee|【Code|A O A U E|igfans|4KGOLD\.COM|Cheapest Gil with|pvp and bank on google|Selling Cheap GIL|ff14mogstation\.com|Cheap Gil 1000k|gilsforyou|server 1000K =|gils_selling|E A S Y\.C O M|bonus code|mins delivery guarantee|Sell cheap NA", - RegexOptions.Compiled); - - private readonly Regex urlRegex = - new Regex(@"(http|ftp|https)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?", - RegexOptions.Compiled); - - private readonly Dictionary retainerSaleRegexes = new Dictionary() { - { - ClientLanguage.Japanese, new Regex[] { - new Regex(@"^(?:.+)マーケットに(?[\d,.]+)ギルで出品した(?.*)×(?[\d,.]+)が売れ、(?[\d,.]+)ギルを入手しました。$", RegexOptions.Compiled), - new Regex(@"^(?:.+)マーケットに(?[\d,.]+)ギルで出品した(?.*)が売れ、(?[\d,.]+)ギルを入手しました。$", RegexOptions.Compiled) - } - }, - { - ClientLanguage.English, new Regex[] - { - new Regex(@"^(?.+) you put up for sale in the (?:.+) markets (?:have|has) sold for (?[\d,.]+) gil \(after fees\)\.$", RegexOptions.Compiled) - } - }, - { - ClientLanguage.German, new Regex[] - { - new Regex(@"^Dein Gehilfe hat (?.+) auf dem Markt von (?:.+) für (?[\d,.]+) Gil verkauft\.$", RegexOptions.Compiled), - new Regex(@"^Dein Gehilfe hat (?.+) auf dem Markt von (?:.+) verkauft und (?[\d,.]+) Gil erhalten\.$", RegexOptions.Compiled) - } - }, - { - ClientLanguage.French, new Regex[] - { - new Regex(@"^Un servant a vendu (?.+) pour (?[\d,.]+) gil à (?:.+)\.$", RegexOptions.Compiled) - } - } - }; - - private bool hasSeenLoadingMsg; - - public ChatHandlers(Dalamud dalamud) { - this.dalamud = dalamud; - - dalamud.Framework.Gui.Chat.OnChatMessageRaw += OnChatMessage; - } - - - public string LastLink { get; private set; } - - private void OnChatMessage(XivChatType type, uint senderId, ref StdString sender, - ref StdString message, ref bool isHandled) { - - if (type == XivChatType.Notice && !this.hasSeenLoadingMsg) { - var assemblyVersion = Assembly.GetAssembly(typeof(ChatHandlers)).GetName().Version.ToString(); - - this.dalamud.Framework.Gui.Chat.Print($"XIVLauncher in-game addon v{assemblyVersion} loaded."); - - foreach (var plugin in this.dalamud.PluginManager.Plugins) { - this.dalamud.Framework.Gui.Chat.Print($" -> {plugin.Plugin.Name} v{plugin.GetType().Assembly.GetName().Version} loaded."); - } - - this.hasSeenLoadingMsg = true; - - if (string.IsNullOrEmpty(this.dalamud.Configuration.LastVersion) || !assemblyVersion.StartsWith(this.dalamud.Configuration.LastVersion)) { - this.dalamud.Framework.Gui.Chat.PrintChat(new XivChatEntry { - MessageBytes = Encoding.UTF8.GetBytes("The In-Game addon has been updated or was reinstalled successfully! Please check the discord for a full changelog."), - Type = XivChatType.Urgent - }); - - this.dalamud.Configuration.LastVersion = assemblyVersion; - this.dalamud.Configuration.Save(this.dalamud.StartInfo.ConfigurationPath); - } - } - -#if !DEBUG && false - if (!this.hasSeenLoadingMsg) - return; -#endif - - var matched = this.rmtRegex.IsMatch(message.Value); - if (matched) { - // This seems to be a RMT ad - let's not show it - Log.Debug("Handled RMT ad"); - isHandled = true; - return; - } - - var messageVal = message.Value; - var senderVal = sender.Value; - - if (this.dalamud.Configuration.BadWords != null && - this.dalamud.Configuration.BadWords.Any(x => messageVal.Contains(x))) { - // This seems to be in the user block list - let's not show it - Log.Debug("Blocklist triggered"); - isHandled = true; - return; - } - - if (type == XivChatType.RetainerSale) - { - foreach (var regex in retainerSaleRegexes[dalamud.StartInfo.Language]) - { - var matchInfo = regex.Match(message.Value); - - // we no longer really need to do/validate the item matching since we read the id from the byte array - // but we'd be checking the main match anyway - var itemInfo = matchInfo.Groups["item"]; - if (!itemInfo.Success) - continue; - - var itemLink = - SeString.Parse(message.RawData).Payloads.First(x => x.Type == PayloadType.Item) as ItemPayload; - - if (itemLink == null) { - Log.Error("itemLink was null. Msg: {0}", BitConverter.ToString(message.RawData)); - break; - } - - Log.Debug($"Probable retainer sale: {message}, decoded item {itemLink.ItemId}, HQ {itemLink.IsHQ}"); - - var valueInfo = matchInfo.Groups["value"]; - // not sure if using a culture here would work correctly, so just strip symbols instead - if (!valueInfo.Success || !int.TryParse(valueInfo.Value.Replace(",", "").Replace(".", ""), out var itemValue)) - continue; - - Task.Run(() => this.dalamud.BotManager.ProcessRetainerSale(itemLink.ItemId, itemValue, itemLink.IsHQ)); - break; - } - } - - var messageCopy = message; - var senderCopy = sender; - Task.Run(() => this.dalamud.BotManager.ProcessChatMessage(type, messageCopy, senderCopy)); - - // Handle all of this with SeString some day - if ((this.HandledChatTypeColors.ContainsKey(type) || type == XivChatType.Say || type == XivChatType.Shout || - type == XivChatType.Alliance || type == XivChatType.TellOutgoing || type == XivChatType.Yell) && !message.Value.Contains((char)0x02)) { - var italicsStart = message.Value.IndexOf("*"); - var italicsEnd = message.Value.IndexOf("*", italicsStart + 1); - - var messageString = message.Value; - - while (italicsEnd != -1) { - var it = MakeItalics( - messageString.Substring(italicsStart, italicsEnd - italicsStart + 1).Replace("*", "")); - messageString = messageString.Remove(italicsStart, italicsEnd - italicsStart + 1); - messageString = messageString.Insert(italicsStart, it); - italicsStart = messageString.IndexOf("*"); - italicsEnd = messageString.IndexOf("*", italicsStart + 1); - } - - message.RawData = Encoding.UTF8.GetBytes(messageString); - } - - - var linkMatch = this.urlRegex.Match(message.Value); - if (linkMatch.Value.Length > 0) - LastLink = linkMatch.Value; - } - - private static string MakeItalics(string text) { - return Encoding.UTF8.GetString(new byte[] {0x02, 0x1A, 0x02, 0x02, 0x03}) + text + - Encoding.UTF8.GetString(new byte[] {0x02, 0x1A, 0x02, 0x01, 0x03}); - } - } -} diff --git a/Dalamud/Game/ClientState/Actors/ActorTable.cs b/Dalamud/Game/ClientState/Actors/ActorTable.cs deleted file mode 100644 index 586404fd1..000000000 --- a/Dalamud/Game/ClientState/Actors/ActorTable.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System; -using System.Collections; -using System.Runtime.InteropServices; -using Dalamud.Game.ClientState.Actors.Types; -using Dalamud.Game.ClientState.Actors.Types.NonPlayer; -using Serilog; - -namespace Dalamud.Game.ClientState.Actors { - /// - /// This collection represents the currently spawned FFXIV actors. - /// - public class ActorTable : ICollection { - private ClientStateAddressResolver Address { get; } - - /// - /// Set up the actor table collection. - /// - /// Client state address resolver. - public ActorTable(ClientStateAddressResolver addressResolver) { - Address = addressResolver; - - Log.Verbose("Actor table address {ActorTable}", Address.ActorTable); - } - - /// - /// Get an actor at the specified spawn index. - /// - /// Spawn index. - /// at the specified spawn index. - public Actor this[int index] { - get { - if (index > Length) - return null; - - //Log.Information("Trying to get actor at {0}", index); - var tblIndex = Address.ActorTable + 8 + index * 8; - - var offset = Marshal.ReadIntPtr(tblIndex); - - //Log.Information("Actor at {0}", offset.ToString()); - - if (offset == IntPtr.Zero) - return null; - - try { - var actorStruct = Marshal.PtrToStructure(offset); - - //Log.Debug("ActorTable[{0}]: {1} - {2} - {3}", index, tblIndex.ToString("X"), offset.ToString("X"), - // actorStruct.ObjectKind.ToString()); - - switch (actorStruct.ObjectKind) - { - case ObjectKind.Player: return new PlayerCharacter(actorStruct); - case ObjectKind.BattleNpc: return new BattleNpc(actorStruct); - default: return new Actor(actorStruct); - } - } catch (AccessViolationException) { - return null; - } - } - } - - private class ActorTableEnumerator : IEnumerator { - private readonly ActorTable table; - - private int currentIndex; - - public ActorTableEnumerator(ActorTable table) { - this.table = table; - } - - public bool MoveNext() { - this.currentIndex++; - return this.currentIndex != this.table.Length; - } - - public void Reset() { - this.currentIndex = 0; - } - - public object Current => this.table[this.currentIndex]; - } - - public IEnumerator GetEnumerator() { - return new ActorTableEnumerator(this); - } - - /// - /// The amount of currently spawned actors. - /// - public int Length => Marshal.ReadInt32(Address.ActorTable); - - int ICollection.Count => Length; - - bool ICollection.IsSynchronized => false; - - object ICollection.SyncRoot => this; - - void ICollection.CopyTo(Array array, int index) { - for (var i = 0; i < Length; i++) { - array.SetValue(this[i], index); - index++; - } - } - } -} diff --git a/Dalamud/Game/ClientState/Actors/ObjectKind.cs b/Dalamud/Game/ClientState/Actors/ObjectKind.cs deleted file mode 100644 index 48af1fdfb..000000000 --- a/Dalamud/Game/ClientState/Actors/ObjectKind.cs +++ /dev/null @@ -1,69 +0,0 @@ -namespace Dalamud.Game.ClientState.Actors { - /// - /// Enum describing possible entity kinds. - /// - public enum ObjectKind : byte { - /// - /// Invalid actor. - /// - None = 0x00, - - /// - /// Objects representing player characters. - /// - Player = 0x01, - - /// - /// Objects representing battle NPCs. - /// - BattleNpc = 0x02, - - /// - /// Objects representing event NPCs. - /// - EventNpc = 0x03, - - /// - /// Objects representing treasures. - /// - Treasure = 0x04, - - /// - /// Objects representing aetherytes. - /// - Aetheryte = 0x05, - - /// - /// Objects representing gathering points. - /// - GatheringPoint = 0x06, - - /// - /// Objects representing event objects. - /// - EventObj = 0x07, - - /// - /// Objects representing mounts. - /// - MountType = 0x08, - - /// - /// Objects representing minions. - /// - Companion = 0x09, // Minion - - /// - /// Objects representing retainers. - /// - Retainer = 0x0A, - Area = 0x0B, - - /// - /// Objects representing housing objects. - /// - Housing = 0x0C, - Cutscene = 0x0D, - CardStand = 0x0E - } -} diff --git a/Dalamud/Game/ClientState/Actors/Position3.cs b/Dalamud/Game/ClientState/Actors/Position3.cs deleted file mode 100644 index 381d1a8de..000000000 --- a/Dalamud/Game/ClientState/Actors/Position3.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Dalamud.Game.ClientState.Actors { - [StructLayout(LayoutKind.Sequential)] - public struct Position3 { - public float X; - public float Z; - public float Y; - } -} diff --git a/Dalamud/Game/ClientState/Actors/Resolvers/ClassJob.cs b/Dalamud/Game/ClientState/Actors/Resolvers/ClassJob.cs deleted file mode 100644 index 82e4b1c42..000000000 --- a/Dalamud/Game/ClientState/Actors/Resolvers/ClassJob.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Actors.Resolvers -{ - /// - /// This object represents a class or job. - /// - public class ClassJob { - /// - /// ID of the ClassJob. - /// - public readonly int Id; - - /// - /// Name of the ClassJob. - /// - public string Name => (string) XivApi.GetClassJob(this.Id).GetAwaiter().GetResult()["Name"]; - - /// - /// Set up the ClassJob resolver with the provided ID. - /// - /// The ID of the world. - public ClassJob(byte id) { - this.Id = id; - } - } -} diff --git a/Dalamud/Game/ClientState/Actors/Resolvers/World.cs b/Dalamud/Game/ClientState/Actors/Resolvers/World.cs deleted file mode 100644 index 53d23cdec..000000000 --- a/Dalamud/Game/ClientState/Actors/Resolvers/World.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Actors.Resolvers -{ - /// - /// This object represents a world a character can reside on. - /// - public class World { - /// - /// ID of the world. - /// - public readonly int Id; - - /// - /// Name of the world. - /// - public string Name => (string) XivApi.GetWorld(this.Id).GetAwaiter().GetResult()["Name"]; - - /// - /// Set up the world resolver with the provided ID. - /// - /// The ID of the world. - public World(byte id) { - this.Id = id; - } - } -} diff --git a/Dalamud/Game/ClientState/Actors/Types/Actor.cs b/Dalamud/Game/ClientState/Actors/Types/Actor.cs deleted file mode 100644 index ae327211f..000000000 --- a/Dalamud/Game/ClientState/Actors/Types/Actor.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace Dalamud.Game.ClientState.Actors.Types { - /// - /// This class represents a basic FFXIV actor. - /// - public class Actor { - /// - /// The memory representation of the base actor. - /// - protected Structs.Actor actorStruct; - - /// - /// Initialize a representation of a basic FFXIV actor. - /// - /// The memory representation of the base actor. - public Actor(Structs.Actor actorStruct) { - this.actorStruct = actorStruct; - } - - /// - /// Position of this . - /// - public Position3 Position => this.actorStruct.Position; - - /// - /// Displayname of this Actor. - /// - public string Name => this.actorStruct.Name; - - /// - /// Actor ID of this . - /// - public int ActorId => this.actorStruct.ActorId; - - /// - /// Entity kind of this actor. See the ObjectKind enum for - /// possible values. - /// - public ObjectKind ObjectKind => this.actorStruct.ObjectKind; - } -} diff --git a/Dalamud/Game/ClientState/Actors/Types/Chara.cs b/Dalamud/Game/ClientState/Actors/Types/Chara.cs deleted file mode 100644 index 60ca0549c..000000000 --- a/Dalamud/Game/ClientState/Actors/Types/Chara.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Dalamud.Game.ClientState.Actors.Resolvers; - -namespace Dalamud.Game.ClientState.Actors.Types { - /// - /// This class represents the base for non-static entities. - /// - public class Chara : Actor { - /// - /// Set up a new Chara with the provided memory representation. - /// - /// The memory representation of the base actor. - public Chara(Structs.Actor actorStruct) : base(actorStruct) { } - - /// - /// The level of this Chara. - /// - public byte Level => this.actorStruct.Level; - - /// - /// The ClassJob of this Chara. - /// - public ClassJob ClassJob => new ClassJob(this.actorStruct.ClassJob); - - /// - /// The current HP of this Chara. - /// - public int CurrentHp => this.actorStruct.CurrentHp; - - /// - /// The maximum HP of this Chara. - /// - public int MaxHp => this.actorStruct.MaxHp; - - /// - /// The current MP of this Chara. - /// - public int CurrentMp => this.actorStruct.CurrentMp; - - /// - /// The maximum MP of this Chara. - /// - public int MaxMp => this.actorStruct.MaxMp; - } -} diff --git a/Dalamud/Game/ClientState/Actors/Types/NonPlayer/BattleNpc.cs b/Dalamud/Game/ClientState/Actors/Types/NonPlayer/BattleNpc.cs deleted file mode 100644 index ea8bf9fcc..000000000 --- a/Dalamud/Game/ClientState/Actors/Types/NonPlayer/BattleNpc.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer { - /// - /// This class represents a battle NPC. - /// - public class BattleNpc : Npc { - /// - /// Set up a new BattleNpc with the provided memory representation. - /// - /// The memory representation of the base actor. - public BattleNpc(Structs.Actor actorStruct) : base(actorStruct) { } - - /// - /// The BattleNpc of this BattleNpc. - /// - public BattleNpcSubKind BattleNpcKind => (BattleNpcSubKind) this.actorStruct.SubKind; - - /// - /// The ID of this BattleNpc's owner. - /// - public int OwnerId => this.actorStruct.OwnerId; - } -} diff --git a/Dalamud/Game/ClientState/Actors/Types/NonPlayer/BattleNpcSubKind.cs b/Dalamud/Game/ClientState/Actors/Types/NonPlayer/BattleNpcSubKind.cs deleted file mode 100644 index f274a0af1..000000000 --- a/Dalamud/Game/ClientState/Actors/Types/NonPlayer/BattleNpcSubKind.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer { - /// - /// Enum describing possible BattleNpc kinds. - /// - public enum BattleNpcSubKind : byte { - /// - /// Invalid BattleNpc. - /// - None = 0, - - /// - /// BattleNpc representing a Pet. - /// - Pet = 2, - - /// - /// BattleNpc representing a standard enemy. - /// - Enemy = 5 - } -} diff --git a/Dalamud/Game/ClientState/Actors/Types/NonPlayer/Npc.cs b/Dalamud/Game/ClientState/Actors/Types/NonPlayer/Npc.cs deleted file mode 100644 index ef0ce3b7c..000000000 --- a/Dalamud/Game/ClientState/Actors/Types/NonPlayer/Npc.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Dalamud.Game.ClientState.Actors.Types.NonPlayer { - /// - /// This class represents a NPC. - /// - public class Npc : Chara { - /// - /// Set up a new NPC with the provided memory representation. - /// - /// The memory representation of the base actor. - public Npc(Structs.Actor actorStruct) : base(actorStruct) { } - - /// - /// The data ID of the NPC linking to their respective game data. - /// - public int DataId => this.actorStruct.DataId; - } -} diff --git a/Dalamud/Game/ClientState/Actors/Types/PlayerCharacter.cs b/Dalamud/Game/ClientState/Actors/Types/PlayerCharacter.cs deleted file mode 100644 index ed09601de..000000000 --- a/Dalamud/Game/ClientState/Actors/Types/PlayerCharacter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Dalamud.Game.ClientState.Actors.Resolvers; - -namespace Dalamud.Game.ClientState.Actors.Types { - /// - /// This class represents a player character. - /// - public class PlayerCharacter : Chara { - /// - /// Set up a new player character with the provided memory representation. - /// - /// The memory representation of the base actor. - public PlayerCharacter(Structs.Actor actorStruct) : base(actorStruct) { } - - /// - /// The current world of the character. - /// - public World CurrentWorld => new World(this.actorStruct.CurrentWorld); - - /// - /// The home world of the character. - /// - public World HomeWorld => new World(this.actorStruct.HomeWorld); - } -} diff --git a/Dalamud/Game/ClientState/ClientState.cs b/Dalamud/Game/ClientState/ClientState.cs deleted file mode 100644 index ade048517..000000000 --- a/Dalamud/Game/ClientState/ClientState.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.ClientState.Actors; -using Dalamud.Game.ClientState.Actors.Types; -using Dalamud.Game.Internal; -using Serilog; - -namespace Dalamud.Game.ClientState -{ - /// - /// This class represents the state of the game client at the time of access. - /// - public class ClientState : INotifyPropertyChanged { - public event PropertyChangedEventHandler PropertyChanged; - - private ClientStateAddressResolver Address { get; } - - public readonly ClientLanguage ClientLanguage; - - /// - /// The table of all present actors. - /// - public readonly ActorTable Actors; - - /// - /// The local player character, if one is present. - /// - //public PlayerCharacter LocalPlayer { get; private set; } - public PlayerCharacter LocalPlayer { - get { - var actor = this.Actors[0]; - - if (actor is PlayerCharacter pc) - return pc; - - return null; - } - } - //public PlayerCharacter LocalPlayer => null; - - /// - /// The content ID of the local character. - /// - public ulong LocalContentId => (ulong) Marshal.ReadInt64(Address.LocalContentId); - - /// - /// The class facilitating Job Gauge data access - /// - public JobGauges JobGauges; - - /// - /// Set up client state access. - /// - /// Dalamud instance - /// /// StartInfo of the current Dalamud launch - /// Sig scanner - /// Game process module - public ClientState(Dalamud dalamud, DalamudStartInfo startInfo, SigScanner scanner, ProcessModule targetModule) { - Address = new ClientStateAddressResolver(); - Address.Setup(scanner); - - Log.Verbose("===== C L I E N T S T A T E ====="); - - this.ClientLanguage = startInfo.Language; - - this.Actors = new ActorTable(Address); - - this.JobGauges = new JobGauges(Address); - - dalamud.Framework.OnUpdateEvent += FrameworkOnOnUpdateEvent; - } - - private void FrameworkOnOnUpdateEvent(Framework framework) { - //LocalPlayer = (PlayerCharacter) this.Actors[0]; - } - } -} diff --git a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs b/Dalamud/Game/ClientState/ClientStateAddressResolver.cs deleted file mode 100644 index ff2dae4f3..000000000 --- a/Dalamud/Game/ClientState/ClientStateAddressResolver.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.Internal; - -namespace Dalamud.Game.ClientState -{ - public sealed class ClientStateAddressResolver : BaseAddressResolver { - public IntPtr ActorTable { get; private set; } - public IntPtr LocalContentId { get; private set; } - public IntPtr JobGaugeData { get; set; } - - protected override void Setup64Bit(SigScanner sig) { - ActorTable = sig.Module.BaseAddress + 0x1C62218; - LocalContentId = sig.Module.BaseAddress + 0x1C2E000; - JobGaugeData = sig.Module.BaseAddress + 0x1C5E4A0; - } - } -} diff --git a/Dalamud/Game/ClientState/JobGauge.cs b/Dalamud/Game/ClientState/JobGauge.cs deleted file mode 100644 index 916921af7..000000000 --- a/Dalamud/Game/ClientState/JobGauge.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Runtime.InteropServices; -using Serilog; - -namespace Dalamud.Game.ClientState { - public class JobGauges { - private ClientStateAddressResolver Address { get; } - - public JobGauges(ClientStateAddressResolver addressResolver) { - Address = addressResolver; - - Log.Verbose("JobGaugeData address {JobGaugeData}", Address.ActorTable); - } - - // Should only be called with the gauge types in - // ClientState.Structs.JobGauge - public T Get() { - return Marshal.PtrToStructure(Address.JobGaugeData); - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs deleted file mode 100644 index f06f19c3d..000000000 --- a/Dalamud/Game/ClientState/Structs/Actor.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.ClientState.Actors; - -namespace Dalamud.Game.ClientState.Structs -{ - /// - /// Native memory representation of a FFXIV actor. - /// - [StructLayout(LayoutKind.Explicit)] - public struct Actor { - [FieldOffset(0x30)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Name; - [FieldOffset(116)] public int ActorId; - [FieldOffset(128)] public int DataId; - [FieldOffset(132)] public int OwnerId; - [FieldOffset(140)] public ObjectKind ObjectKind; - [FieldOffset(141)] public byte SubKind; - [FieldOffset(160)] public Position3 Position; - [FieldOffset(6276)] public byte CurrentWorld; - [FieldOffset(6278)] public byte HomeWorld; - [FieldOffset(6328)] public int CurrentHp; - [FieldOffset(6332)] public int MaxHp; - [FieldOffset(6336)] public int CurrentMp; - [FieldOffset(6340)] public int MaxMp; - [FieldOffset(6358)] public byte ClassJob; - [FieldOffset(6360)] public byte Level; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs deleted file mode 100644 index e6eca6548..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/ASTGauge.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct ASTGauge { - [FieldOffset(4)] private CardType Card; - [FieldOffset(5)] private unsafe fixed byte Seals[3]; - - public CardType DrawnCard() { - return Card; - } - - public unsafe bool ContainsSeal(SealType seal) { - if (Seals[0] == (byte)seal) return true; - if (Seals[1] == (byte)seal) return true; - if (Seals[2] == (byte)seal) return true; - return false; - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs deleted file mode 100644 index 8bbb74610..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/BLMGauge.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct BLMGauge { - [FieldOffset(0)] public short TimeUntilNextPolyglot; //eno timer (ms) - [FieldOffset(2)] public short ElementTimeRemaining; //ui/af timer - [FieldOffset(4)] private byte ElementStance; //ui/af - [FieldOffset(5)] public byte NumUmbralHearts; //number of umbral hearts - [FieldOffset(6)] public byte NumPolyglotStacks; //number of polyglot stacks - [FieldOffset(7)] private byte EnoState; //eno active? - - public bool InUmbralIce() { - return ElementStance > 4; - } - - public bool InAstralFire() { - return ElementStance > 0 && ElementStance < 4; - } - - public bool IsEnoActive() { - return EnoState > 0; - } - - } - - -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs deleted file mode 100644 index 11eb1f5ad..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/BRDGauge.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct BRDGauge { - [FieldOffset(0)] public short SongTimer; - [FieldOffset(2)] public byte NumSongStacks; - [FieldOffset(4)] public CurrentSong ActiveSong; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs deleted file mode 100644 index b77e6f0e4..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DNCGauge.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public unsafe struct DNCGauge { - [FieldOffset(0)] public byte NumFeathers; - [FieldOffset(1)] public byte Esprit; - [FieldOffset(2)] private fixed byte StepOrder[4]; - [FieldOffset(6)] public byte NumCompleteSteps; - - public bool IsDancing() { - return StepOrder[0] != 0; - } - - public ulong NextStep() { - return (ulong)(15999 + StepOrder[NumCompleteSteps] - 1); - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs deleted file mode 100644 index fa71eb541..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRGGauge.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct DRGGauge { - [FieldOffset(0)] public short BOTDTimer; - [FieldOffset(2)] public BOTDState BOTDState; - [FieldOffset(3)] public byte EyeCount; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs deleted file mode 100644 index 5c711cf57..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/DRKGauge.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - [StructLayout(LayoutKind.Explicit)] - public struct DRKGauge { - [FieldOffset(0)] public byte Blood; - [FieldOffset(2)] public short DarksideTimeRemaining; - [FieldOffset(4)] private byte DarkArtsState; - [FieldOffset(6)] public short ShadowTimeRemaining; - - public bool HasDarkArts() { - return DarkArtsState > 0; - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs deleted file mode 100644 index 969adda1d..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/GNBGauge.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct GNBGauge { - [FieldOffset(0)] public byte NumAmmo; - [FieldOffset(2)] public short MaxTimerDuration; - [FieldOffset(4)] public byte AmmoComboStepNumber; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs b/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs deleted file mode 100644 index 69762e295..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/JobEnums.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - public enum SealType : byte { - NONE = 0, - SUN, - MOON, - CELESTIAL - } - - public enum CardType : byte { - NONE = 0, - BALANCE, - BOLE, - ARROW, - SPEAR, - EWER, - SPIRE, - LORD = 0x70, - LADY = 0x80 - } - - public enum SummonPet : byte { - NONE = 0, - IFRIT = 3, - TITAN, - GARUDA - } - - public enum PetGlam : byte { - NONE = 0, - EMERALD, - TOPAZ, - RUBY - } - - [Flags] - public enum Sen : byte { - NONE = 0, - SETSU = 1 << 0, - GETSU = 1 << 1, - KA = 1 << 2 - } - - public enum BOTDState : byte { - NONE = 0, - BOTD, - LOTD - } - - public enum CurrentSong : byte { - MAGE = 5, - ARMY = 0xA, - WANDERER = 0xF - } - - public enum DismissedFairy : byte { - EOS = 6, - SELENE - } - - public enum Mudras : byte { - TEN = 1, - CHI = 2, - JIN = 3 - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs deleted file mode 100644 index e606cb751..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/MCHGauge.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct MCHGauge{ - - [FieldOffset(0)] public short OverheatTimeRemaining; - [FieldOffset(2)] public short RobotTimeRemaining; - [FieldOffset(4)] public byte Heat; - [FieldOffset(5)] public byte Battery; - [FieldOffset(6)] public byte LastRobotBatteryPower; - [FieldOffset(7)] private byte TimerActive; - - public bool IsOverheated() { - return (TimerActive & 1) != 0; - } - public bool IsRobotActive() { - return (TimerActive & 2) != 0; - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs deleted file mode 100644 index 0d40ee780..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/MNKGauge.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct MNKGauge { - [FieldOffset(0)] public byte GLTimer; - [FieldOffset(2)] public byte NumGLStacks; - [FieldOffset(3)] public byte NumChakra; - [FieldOffset(4)] private byte GLTimerFreezeState; - - public bool IsGLTimerFroze() { - return GLTimerFreezeState > 0; - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs deleted file mode 100644 index 672e27b81..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/NINGauge.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct NINGauge { - [FieldOffset(0)] public int HutonTimeLeft; - [FieldOffset(4)] public byte TCJMudrasUsed; //some sort of mask - [FieldOffset(5)] public byte Ninki; - [FieldOffset(6)] public byte NumHutonManualCasts; //wtf - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs deleted file mode 100644 index 30b7f65e3..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/PLDGauge.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct PLDGauge { - [FieldOffset(0)] public byte GaugeAmount; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs deleted file mode 100644 index b0a2fa0c6..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/RDMGauge.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct RDMGauge { - [FieldOffset(0)] public byte WhiteGauge; - [FieldOffset(1)] public byte BlackGauge; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs deleted file mode 100644 index 6c10ba477..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SAMGauge.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct SAMGauge { - - [FieldOffset(3)] public byte Kenki; - [FieldOffset(4)] public Sen Sen; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs deleted file mode 100644 index 5d742ee0e..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SCHGauge.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct SCHGauge { - [FieldOffset(2)] public byte NumAetherflowStacks; - [FieldOffset(3)] public byte FairyGaugeAmount; - [FieldOffset(4)] public short SeraphTimer; - [FieldOffset(6)] public DismissedFairy DismissedFairy; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs deleted file mode 100644 index 1742f4d97..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/SMNGauge.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct SMNGauge { - - //Unfinished - [FieldOffset(0)] public short TimerRemaining; - [FieldOffset(2)] public SummonPet ReturnSummon; - [FieldOffset(3)] public PetGlam ReturnSummonGlam; - [FieldOffset(4)] public byte NumStacks; - - public bool IsPhoenixReady() { - return (NumStacks & 0x10) > 0; - } - - public bool IsBahamutReady() { - return (NumStacks & 8) > 0; - } - - public bool HasAetherflowStacks() { - return (NumStacks & 3) > 0; - } - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs deleted file mode 100644 index ed1ecf364..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/WARGauge.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct WARGauge { - [FieldOffset(0)] public byte BeastGaugeAmount; - } -} diff --git a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs b/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs deleted file mode 100644 index a5ad15906..000000000 --- a/Dalamud/Game/ClientState/Structs/JobGauge/WHMGauge.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.ClientState.Structs.JobGauge { - - [StructLayout(LayoutKind.Explicit)] - public struct WHMGauge { - [FieldOffset(2)] public short LilyTimer; //Counts to 30k = 30s - [FieldOffset(4)] public byte NumLilies; - [FieldOffset(5)] public byte NumBloodLily; - } -} diff --git a/Dalamud/Game/Command/CommandInfo.cs b/Dalamud/Game/Command/CommandInfo.cs deleted file mode 100644 index 3905a843c..000000000 --- a/Dalamud/Game/Command/CommandInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Dalamud.Game.Command { - /// - /// This class describes a registered command. - /// - public sealed class CommandInfo { - /// - /// The function to be executed when the command is dispatched. - /// - /// The command itself. - /// The arguments supplied to the command, ready for parsing. - public delegate void HandlerDelegate(string command, string arguments); - - /// - /// A which will be called when the command is dispatched. - /// - public HandlerDelegate Handler { get; } - - /// - /// The help message for this command. - /// - public string HelpMessage { get; set; } = string.Empty; - - /// - /// If this command should be shown in the help output. - /// - public bool ShowInHelp { get; set; } = true; - - /// - /// Create a new CommandInfo with the provided handler. - /// - /// - public CommandInfo(HandlerDelegate handler) { - Handler = handler; - } - } -} diff --git a/Dalamud/Game/Command/CommandManager.cs b/Dalamud/Game/Command/CommandManager.cs deleted file mode 100644 index aad85dfec..000000000 --- a/Dalamud/Game/Command/CommandManager.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Text.RegularExpressions; -using Dalamud.Game.Chat; -using Dalamud.Game.Internal.Libc; -using Serilog; - -namespace Dalamud.Game.Command { - /// - /// This class manages registered in-game slash commands. - /// - public sealed class CommandManager { - private readonly Dalamud dalamud; - - private readonly Dictionary commandMap = new Dictionary(); - - /// - /// Read-only list of all registered commands. - /// - public ReadOnlyDictionary Commands => - new ReadOnlyDictionary(this.commandMap); - - private readonly Regex commandRegexEn = - new Regex(@"^The command (?.+) does not exist\.$", RegexOptions.Compiled); - - private readonly Regex commandRegexJp = new Regex(@"^そのコマンドはありません。: (?.+)$", RegexOptions.Compiled); - - private readonly Regex commandRegexDe = - new Regex(@"^„(?.+)“ existiert nicht als Textkommando\.$", RegexOptions.Compiled); - - private readonly Regex commandRegexFr = - new Regex(@"^La commande texte “(?.+)” n'existe pas\.$", - RegexOptions.Compiled); - - private readonly Regex currentLangCommandRegex; - - - public CommandManager(Dalamud dalamud, ClientLanguage language) { - this.dalamud = dalamud; - - switch (language) { - case ClientLanguage.Japanese: - this.currentLangCommandRegex = this.commandRegexJp; - break; - case ClientLanguage.English: - this.currentLangCommandRegex = this.commandRegexEn; - break; - case ClientLanguage.German: - this.currentLangCommandRegex = this.commandRegexDe; - break; - case ClientLanguage.French: - this.currentLangCommandRegex = this.commandRegexFr; - break; - } - - dalamud.Framework.Gui.Chat.OnChatMessageRaw += OnChatMessage; - } - - private void OnChatMessage(XivChatType type, uint senderId, ref StdString sender, - ref StdString message, ref bool isHandled) { - if (type == XivChatType.GatheringSystemMessage && senderId == 0) { - var cmdMatch = this.currentLangCommandRegex.Match(message.Value).Groups["command"]; - if (cmdMatch.Success) { - // Yes, it's a chat command. - var command = cmdMatch.Value; - if (ProcessCommand(command)) isHandled = true; - } - } - } - - private bool ProcessCommand(string content) { - string command; - string argument; - - var speratorPosition = content.IndexOf(' '); - if (speratorPosition == -1 || speratorPosition + 1 >= content.Length) { - // If no space was found or ends with the space. Process them as a no argument - command = content; - argument = string.Empty; - } else { - // e.g.) - // /testcommand arg1 - // => Total of 17 chars - // => command: 0-12 (12 chars) - // => argument: 13-17 (4 chars) - // => content.IndexOf(' ') == 12 - command = content.Substring(0, speratorPosition); - - var argStart = speratorPosition + 1; - argument = content.Substring(argStart, content.Length - argStart); - } - - if (!this.commandMap.TryGetValue(command, out var handler)) // Commad was not found. - return false; - - DispatchCommand(command, argument, handler); - return true; - } - - /// - /// Dispatch the handling of a command. - /// - /// The command to dispatch. - /// The provided arguments. - /// A object describing this command. - public void DispatchCommand(string command, string argument, CommandInfo info) { - try { - info.Handler(command, argument); - } catch (Exception ex) { - Log.Error(ex, "Error while dispatching command {CommandName} (Argument: {Argument})", command, - argument); - } - } - - /// - /// Add a command handler, which you can use to add your own custom commands to the in-game chat. - /// - /// The command to register. - /// A object describing the command. - /// If adding was successful. - public bool AddHandler(string command, CommandInfo info) { - if (info == null) throw new ArgumentNullException(nameof(info), "Command handler is null."); - - try { - this.commandMap.Add(command, info); - return true; - } catch (ArgumentException) { - Log.Error("Command {CommandName} is already registered.", command); - return false; - } - } - - /// - /// Remove a command from the command handlers. - /// - /// The command to remove. - /// If the removal was successful. - public bool RemoveHandler(string command) { - return this.commandMap.Remove(command); - } - } -} diff --git a/Dalamud/Game/Internal/AntiDebug.cs b/Dalamud/Game/Internal/AntiDebug.cs deleted file mode 100644 index 6ce25488b..000000000 --- a/Dalamud/Game/Internal/AntiDebug.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Hooking; -using EasyHook; -using Serilog; - -namespace Dalamud.Game.Internal -{ - class AntiDebug : IDisposable - { - [UnmanagedFunctionPointer(CallingConvention.Winapi)] - private delegate bool IsDebuggerPresentDelegate(); - - private Hook debuggerPresentHook; - - public AntiDebug() { - this.debuggerPresentHook = new Hook(LocalHook.GetProcAddress("Kernel32", "IsDebuggerPresent"), - new IsDebuggerPresentDelegate(IsDebuggerPresentDetour)); - - Log.Verbose("IsDebuggerPresent address {IsDebuggerPresent}", this.debuggerPresentHook.Address); - } - - public void Enable() { - this.debuggerPresentHook.Enable(); - } - - public void Dispose() { - this.debuggerPresentHook.Disable(); - } - - private bool IsDebuggerPresentDetour() { - return false; - } - } -} diff --git a/Dalamud/Game/Internal/BaseAddressResolver.cs b/Dalamud/Game/Internal/BaseAddressResolver.cs deleted file mode 100644 index 8cbb83be5..000000000 --- a/Dalamud/Game/Internal/BaseAddressResolver.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Dalamud.Game.Internal { - public abstract class BaseAddressResolver { - protected bool IsResolved { get; set; } - - public void Setup(SigScanner scanner) { - // Because C# don't allow to call virtual function while in ctor - // we have to do this shit :\ - - if (IsResolved) { - return; - } - - if (scanner.Is32BitProcess) { - Setup32Bit(scanner); - } else { - Setup64Bit(scanner); - } - SetupInternal(scanner); - - IsResolved = true; - } - - protected virtual void Setup32Bit(SigScanner scanner) { - throw new NotSupportedException("32 bit version is not supported."); - } - - protected virtual void Setup64Bit(SigScanner sig) { - throw new NotSupportedException("64 bit version is not supported."); - } - - protected virtual void SetupInternal(SigScanner scanner) { - // Do nothing - } - - protected T GetVirtualFunction(IntPtr address, int vtableOffset, int count) where T : class { - // Get vtable - var vtable = Marshal.ReadIntPtr(address, vtableOffset); - - // Get an address to the function - var functionAddress = Marshal.ReadIntPtr(vtable, IntPtr.Size * count); - - return Marshal.GetDelegateForFunctionPointer(functionAddress); - } - } -} diff --git a/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs b/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs deleted file mode 100644 index ad2e003f6..000000000 --- a/Dalamud/Game/Internal/DXGI/ISwapChainAddressResolver.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System; - -namespace Dalamud.Game.Internal.DXGI { - public interface ISwapChainAddressResolver { - IntPtr Present { get; set; } - } -} diff --git a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs deleted file mode 100644 index 37c28197e..000000000 --- a/Dalamud/Game/Internal/DXGI/SwapChainSigResolver.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Serilog; - -namespace Dalamud.Game.Internal.DXGI -{ - public sealed class SwapChainSigResolver : BaseAddressResolver, ISwapChainAddressResolver - { - public IntPtr Present { get; set; } - //public IntPtr ResizeBuffers { get; private set; } - - protected override void Setup64Bit(SigScanner sig) - { - var module = Process.GetCurrentProcess().Modules.Cast().First(m => m.ModuleName == "dxgi.dll"); - - Log.Debug($"Found DXGI: {module.BaseAddress.ToInt64():X}"); - - var scanner = new SigScanner(module); - - // This(code after the function head - offset of it) was picked to avoid running into issues with other hooks being installed into this function. - Present = scanner.ScanModule("41 8B F0 8B FA 89 54 24 ?? 48 8B D9 48 89 4D ?? C6 44 24 ?? 00") - 0x37; - - - // seems unnecessary for now, but we may need to handle it - //ResizeBuffers = scanner.ScanModule("48 8B C4 55 41 54 41 55 41 56 41 57 48 8D 68 ?? 48 81 EC C0 00 00 00"); - } - } -} diff --git a/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs b/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs deleted file mode 100644 index a9981b8ed..000000000 --- a/Dalamud/Game/Internal/DXGI/SwapChainVtableResolver.cs +++ /dev/null @@ -1,98 +0,0 @@ -using SharpDX.Direct3D; -using SharpDX.Direct3D11; -using SharpDX.DXGI; -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using SharpDX.Windows; -using Device = SharpDX.Direct3D11.Device; - -namespace Dalamud.Game.Internal.DXGI -{ - /* - * This method of getting the SwapChain Addresses is currently not used. - * If the normal AddressResolver(SigScanner) fails, we should use it as a fallback.(Linux?) - */ - public class SwapChainVtableResolver : BaseAddressResolver, ISwapChainAddressResolver - { - private const int DxgiSwapchainMethodCount = 18; - private const int D3D11DeviceMethodCount = 43; - - private static SwapChainDescription CreateSwapChainDescription(IntPtr renderForm) { - return new SwapChainDescription { - BufferCount = 1, - Flags = SwapChainFlags.None, - IsWindowed = true, - ModeDescription = new ModeDescription(100, 100, new Rational(60, 1), Format.R8G8B8A8_UNorm), - OutputHandle = renderForm, - SampleDescription = new SampleDescription(1, 0), - SwapEffect = SwapEffect.Discard, - Usage = Usage.RenderTargetOutput - }; - } - - private IntPtr[] GetVTblAddresses(IntPtr pointer, int numberOfMethods) - { - return GetVTblAddresses(pointer, 0, numberOfMethods); - } - - private IntPtr[] GetVTblAddresses(IntPtr pointer, int startIndex, int numberOfMethods) - { - List vtblAddresses = new List(); - IntPtr vTable = Marshal.ReadIntPtr(pointer); - for (int i = startIndex; i < startIndex + numberOfMethods; i++) - vtblAddresses.Add(Marshal.ReadIntPtr(vTable, i * IntPtr.Size)); // using IntPtr.Size allows us to support both 32 and 64-bit processes - - return vtblAddresses.ToArray(); - } - - private List d3d11VTblAddresses = null; - private List dxgiSwapChainVTblAddresses = null; - - #region Internal device resources - - private Device device; - private SwapChain swapChain; - private RenderForm renderForm; - #endregion - - #region Addresses - - public IntPtr Present { get; set; } - - #endregion - - protected override void Setup64Bit(SigScanner sig) { - if (this.d3d11VTblAddresses == null) { - this.d3d11VTblAddresses = new List(); - this.dxgiSwapChainVTblAddresses = new List(); - - #region Get Device and SwapChain method addresses - - // Create temporary device + swapchain and determine method addresses - this.renderForm = new RenderForm(); - Device.CreateWithSwapChain( - DriverType.Hardware, - DeviceCreationFlags.BgraSupport, - CreateSwapChainDescription(this.renderForm.Handle), - out this.device, - out this.swapChain - ); - - if (this.device != null && this.swapChain != null) { - this.d3d11VTblAddresses.AddRange( - GetVTblAddresses(this.device.NativePointer, D3D11DeviceMethodCount)); - this.dxgiSwapChainVTblAddresses.AddRange( - GetVTblAddresses(this.swapChain.NativePointer, DxgiSwapchainMethodCount)); - } - - this.device?.Dispose(); - this.swapChain?.Dispose(); - - #endregion - } - - Present = this.dxgiSwapChainVTblAddresses[8]; - } - } -} diff --git a/Dalamud/Game/Internal/Framework.cs b/Dalamud/Game/Internal/Framework.cs deleted file mode 100644 index 31ede43cc..000000000 --- a/Dalamud/Game/Internal/Framework.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Dalamud.Game.Internal.Gui; -using Dalamud.Game.Internal.Libc; -using Dalamud.Game.Internal.Network; -using Dalamud.Hooking; -using Serilog; -using Dalamud.Game.Internal.File; - -namespace Dalamud.Game.Internal { - /// - /// This class represents the Framework of the native game client and grants access to various subsystems. - /// - public sealed class Framework : IDisposable { - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate bool OnUpdateDetour(IntPtr framework); - - public delegate void OnUpdateDelegate(Framework framework); - - public event OnUpdateDelegate OnUpdateEvent; - - private Hook updateHook; - - - /// - /// A raw pointer to the instance of Client::Framework - /// - private FrameworkAddressResolver Address { get; } - -#region Subsystems - - /// - /// The GUI subsystem, used to access e.g. chat. - /// - public GameGui Gui { get; private set; } - - /// - /// The Network subsystem, used to access network data. - /// - public GameNetwork Network { get; private set; } - - //public ResourceManager Resource { get; private set; } - - public LibcFunction Libc { get; private set; } - - private AntiDebug antiDebug; - -#endregion - - public Framework(SigScanner scanner, Dalamud dalamud) { - Address = new FrameworkAddressResolver(); - Address.Setup(scanner); - - Log.Verbose("Framework address {FrameworkAddress}", Address.BaseAddress); - if (Address.BaseAddress == IntPtr.Zero) { - throw new InvalidOperationException("Framework is not initalized yet."); - } - - // Hook virtual functions - HookVTable(); - - // Initialize subsystems - Libc = new LibcFunction(scanner); - - Gui = new GameGui(Address.GuiManager, scanner, dalamud); - - Network = new GameNetwork(dalamud, scanner); - - //Resource = new ResourceManager(dalamud, scanner); - - this.antiDebug = new AntiDebug(); - } - - private void HookVTable() { - var vtable = Marshal.ReadIntPtr(Address.BaseAddress); - // Virtual function layout: - // .rdata:00000001411F1FE0 dq offset Xiv__Framework___dtor - // .rdata:00000001411F1FE8 dq offset Xiv__Framework__init - // .rdata:00000001411F1FF0 dq offset sub_1400936E0 - // .rdata:00000001411F1FF8 dq offset sub_1400939E0 - // .rdata:00000001411F2000 dq offset Xiv__Framework__update - - var pUpdate = Marshal.ReadIntPtr(vtable, IntPtr.Size * 4); - this.updateHook = new Hook(pUpdate, new OnUpdateDetour(HandleFrameworkUpdate), this); - } - - public void Enable() { - this.antiDebug.Enable(); - Gui.Enable(); - Network.Enable(); - //Resource.Enable(); - - this.updateHook.Enable(); - } - - public void Dispose() { - this.antiDebug.Dispose(); - Gui.Dispose(); - Network.Dispose(); - //Resource.Dispose(); - - this.updateHook.Dispose(); - } - - private bool HandleFrameworkUpdate(IntPtr framework) { - try { - Gui.Chat.UpdateQueue(this); - Network.UpdateQueue(this); - } catch (Exception ex) { - Log.Error(ex, "Exception while handling Framework::Update hook."); - } - - try { - OnUpdateEvent?.Invoke(this); - } catch (Exception ex) { - Log.Error(ex, "Exception while dispatching Framework::Update event."); - } - - return this.updateHook.Original(framework); - } - } -} diff --git a/Dalamud/Game/Internal/FrameworkAddressResolver.cs b/Dalamud/Game/Internal/FrameworkAddressResolver.cs deleted file mode 100644 index 6d6b11263..000000000 --- a/Dalamud/Game/Internal/FrameworkAddressResolver.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System; -using System.Runtime.InteropServices; - -namespace Dalamud.Game.Internal { - public sealed class FrameworkAddressResolver : BaseAddressResolver { - public IntPtr BaseAddress { get; private set; } - - public IntPtr GuiManager { get; private set; } - - public IntPtr ScriptManager { get; private set; } - - - protected override void Setup64Bit(SigScanner sig) { - SetupFramework(sig); - - // Xiv__Framework__GetGuiManager+8 000 mov rax, [rcx+2C00h] - // Xiv__Framework__GetGuiManager+F 000 retn - GuiManager = Marshal.ReadIntPtr(BaseAddress, 0x2C08); - - // Called from Framework::Init - ScriptManager = BaseAddress + 0x2C68; // note that no deref here - } - - private void SetupFramework(SigScanner scanner) { - // Dissasembly of part of the .dtor - // 00007FF701AD665A | 48 C7 05 ?? ?? ?? ?? 00 00 00 00 | MOV QWORD PTR DS:[g_mainFramework],0 - // 00007FF701AD6665 | E8 ?? ?? ?? ?? | CALL ffxiv_dx11.7FF701E27130 - // 00007FF701AD666A | 48 8D ?? ?? ?? 00 00 | LEA RCX,QWORD PTR DS:[RBX + 2C38] - // 00007FF701AD6671 | E8 ?? ?? ?? ?? | CALL ffxiv_dx11.7FF701E2A7D0 - // 00007FF701AD6676 | 48 8D ?? ?? ?? ?? ?? | LEA RAX,QWORD PTR DS:[7FF702C31F80 - var fwDtor = scanner.ScanText("48C705????????00000000 E8???????? 488D??????0000 E8???????? 488D"); - var fwOffset = Marshal.ReadInt32(fwDtor + 3); - var pFramework = scanner.ResolveRelativeAddress(fwDtor + 11, fwOffset); - - // Framework does not change once initialized in startup so don't bother to deref again and again. - BaseAddress = Marshal.ReadIntPtr(pFramework); - } - } -} diff --git a/Dalamud/Game/Internal/Gui/ChatGui.cs b/Dalamud/Game/Internal/Gui/ChatGui.cs deleted file mode 100644 index c9eb128c9..000000000 --- a/Dalamud/Game/Internal/Gui/ChatGui.cs +++ /dev/null @@ -1,209 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; -using Dalamud.Game.Chat; -using Dalamud.Game.Chat.SeStringHandling; -using Dalamud.Game.Internal.Libc; -using Dalamud.Hooking; -using Discord.Rest; -using Serilog; - -namespace Dalamud.Game.Internal.Gui { - public sealed class ChatGui : IDisposable { - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr PrintMessageDelegate(IntPtr manager, XivChatType chatType, IntPtr senderName, - IntPtr message, - uint senderId, IntPtr parameter); - - public delegate void OnMessageDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, - ref bool isHandled); - - public delegate void OnMessageRawDelegate(XivChatType type, uint senderId, ref StdString sender, ref StdString message, - ref bool isHandled); - - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate void PopulateItemLinkDelegate(IntPtr linkObjectPtr, IntPtr itemInfoPtr); - - private readonly Queue chatQueue = new Queue(); - - private readonly Hook printMessageHook; - - public event OnMessageDelegate OnChatMessage; - [Obsolete("Please use OnChatMessage instead. For modifications, it will take precedence.")] - public event OnMessageRawDelegate OnChatMessageRaw; - - private readonly Hook populateItemLinkHook; - - public int LastLinkedItemId { get; private set; } - public byte LastLinkedItemFlags { get; private set; } - - private ChatGuiAddressResolver Address { get; } - - private IntPtr baseAddress = IntPtr.Zero; - - private readonly Dalamud dalamud; - - public ChatGui(IntPtr baseAddress, SigScanner scanner, Dalamud dalamud) { - this.dalamud = dalamud; - - Address = new ChatGuiAddressResolver(baseAddress); - Address.Setup(scanner); - - Log.Verbose("Chat manager address {ChatManager}", Address.BaseAddress); - - this.printMessageHook = - new Hook(Address.PrintMessage, new PrintMessageDelegate(HandlePrintMessageDetour), - this); - this.populateItemLinkHook = - new Hook(Address.PopulateItemLinkObject, - new PopulateItemLinkDelegate(HandlePopulateItemLinkDetour), - this); - } - - public void Enable() { - this.printMessageHook.Enable(); - this.populateItemLinkHook.Enable(); - } - - public void Dispose() { - this.printMessageHook.Dispose(); - this.populateItemLinkHook.Dispose(); - } - - private void HandlePopulateItemLinkDetour(IntPtr linkObjectPtr, IntPtr itemInfoPtr) { - try { - this.populateItemLinkHook.Original(linkObjectPtr, itemInfoPtr); - - LastLinkedItemId = Marshal.ReadInt32(itemInfoPtr, 8); - LastLinkedItemFlags = Marshal.ReadByte(itemInfoPtr, 0x14); - - Log.Debug($"HandlePopulateItemLinkDetour {linkObjectPtr} {itemInfoPtr} - linked:{LastLinkedItemId}"); - } catch (Exception ex) { - Log.Error(ex, "Exception onPopulateItemLink hook."); - this.populateItemLinkHook.Original(linkObjectPtr, itemInfoPtr); - } - } - - private IntPtr HandlePrintMessageDetour(IntPtr manager, XivChatType chattype, IntPtr pSenderName, IntPtr pMessage, - uint senderid, IntPtr parameter) { - var retVal = IntPtr.Zero; - - try { - var sender = StdString.ReadFromPointer(pSenderName); - var message = StdString.ReadFromPointer(pMessage); - - var parsedSender = SeString.Parse(sender.RawData); - var parsedMessage = SeString.Parse(message.RawData); - - //Log.Debug($"HandlePrintMessageDetour {manager} - [{chattype}] [{BitConverter.ToString(message.RawData).Replace("-", " ")}] {message.Value} from {senderName.Value}"); - - var originalMessageData = (byte[]) message.RawData.Clone(); - var oldEdited = parsedMessage.Encode(); - - // Call events - var isHandled = false; - OnChatMessage?.Invoke(chattype, senderid, ref parsedSender, ref parsedMessage, ref isHandled); - OnChatMessageRaw?.Invoke(chattype, senderid, ref sender, ref message, ref isHandled); - - var newEdited = parsedMessage.Encode(); - - if (!FastByteArrayCompare(oldEdited, newEdited)) { - Log.Verbose("SeString was edited, taking precedence over StdString edit."); - message.RawData = newEdited; - } - Log.Debug($"\nOLD: {BitConverter.ToString(originalMessageData)}\nNEW: {BitConverter.ToString(newEdited)}"); - - var messagePtr = pMessage; - OwnedStdString allocatedString = null; - - if (!FastByteArrayCompare(originalMessageData, message.RawData)) { - allocatedString = this.dalamud.Framework.Libc.NewString(message.RawData); - Log.Debug( - $"HandlePrintMessageDetour String modified: {originalMessageData}({messagePtr}) -> {message}({allocatedString.Address})"); - messagePtr = allocatedString.Address; - } - - // Print the original chat if it's handled. - if (!isHandled) - retVal = this.printMessageHook.Original(manager, chattype, pSenderName, messagePtr, senderid, parameter); - - if (this.baseAddress == IntPtr.Zero) - this.baseAddress = manager; - - allocatedString?.Dispose(); - } catch (Exception ex) { - Log.Error(ex, "Exception on OnChatMessage hook."); - retVal = this.printMessageHook.Original(manager, chattype, pSenderName, pMessage, senderid, parameter); - } - - return retVal; - } - - // Copyright (c) 2008-2013 Hafthor Stefansson - // Distributed under the MIT/X11 software license - // Ref: http://www.opensource.org/licenses/mit-license.php. - // https://stackoverflow.com/a/8808245 - static unsafe bool FastByteArrayCompare(byte[] a1, byte[] a2) - { - if (a1 == a2) return true; - if (a1 == null || a2 == null || a1.Length != a2.Length) - return false; - fixed (byte* p1 = a1, p2 = a2) - { - byte* x1 = p1, x2 = p2; - int l = a1.Length; - for (int i = 0; i < l / 8; i++, x1 += 8, x2 += 8) - if (*((long*)x1) != *((long*)x2)) return false; - if ((l & 4) != 0) { if (*((int*)x1) != *((int*)x2)) return false; x1 += 4; x2 += 4; } - if ((l & 2) != 0) { if (*((short*)x1) != *((short*)x2)) return false; x1 += 2; x2 += 2; } - if ((l & 1) != 0) if (*((byte*)x1) != *((byte*)x2)) return false; - return true; - } - } - - /// - /// Queue a chat message. While method is named as PrintChat, it only add a entry to the queue, - /// later to be processed when UpdateQueue() is called. - /// - /// A message to send. - public void PrintChat(XivChatEntry chat) { - this.chatQueue.Enqueue(chat); - } - - public void Print(string message) { - PrintChat(new XivChatEntry { - MessageBytes = Encoding.UTF8.GetBytes(message) - }); - } - - public void PrintError(string message) { - PrintChat(new XivChatEntry { - MessageBytes = Encoding.UTF8.GetBytes(message), - Type = XivChatType.Urgent - }); - } - - /// - /// Process a chat queue. - /// - public void UpdateQueue(Framework framework) { - while (this.chatQueue.Count > 0) { - var chat = this.chatQueue.Dequeue(); - - var sender = chat.Name ?? ""; - var message = chat.MessageBytes ?? new byte[0]; - - if (this.baseAddress != IntPtr.Zero) - using (var senderVec = framework.Libc.NewString(Encoding.UTF8.GetBytes(sender))) - using (var messageVec = framework.Libc.NewString(message)) - { - Log.Verbose($"String allocated to {messageVec.Address.ToInt64():X}"); - this.printMessageHook.Original(this.baseAddress, chat.Type, senderVec.Address, - messageVec.Address, chat.SenderId, chat.Parameters); - } - } - } - } -} diff --git a/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs deleted file mode 100644 index bc4d7b0f9..000000000 --- a/Dalamud/Game/Internal/Gui/ChatGuiAddressResolver.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; - -namespace Dalamud.Game.Internal.Gui { - public sealed class ChatGuiAddressResolver : BaseAddressResolver { - public IntPtr BaseAddress { get; } - - public IntPtr PrintMessage { get; private set; } - public IntPtr PopulateItemLinkObject { get; private set; } - - public ChatGuiAddressResolver(IntPtr baseAddres) { - BaseAddress = baseAddres; - } - - - /* - --- for reference: 4.57 --- - -.text:00000001405CD210 ; __int64 __fastcall Xiv::Gui::ChatGui::PrintMessage(__int64 handler, unsigned __int16 chatType, __int64 senderName, __int64 message, int senderActorId, char isLocal) -.text:00000001405CD210 Xiv__Gui__ChatGui__PrintMessage proc near -.text:00000001405CD210 ; CODE XREF: sub_1401419F0+201↑p -.text:00000001405CD210 ; sub_140141D10+220↑p ... -.text:00000001405CD210 -.text:00000001405CD210 var_220 = qword ptr -220h -.text:00000001405CD210 var_218 = byte ptr -218h -.text:00000001405CD210 var_210 = word ptr -210h -.text:00000001405CD210 var_208 = byte ptr -208h -.text:00000001405CD210 var_200 = word ptr -200h -.text:00000001405CD210 var_1FC = dword ptr -1FCh -.text:00000001405CD210 var_1F8 = qword ptr -1F8h -.text:00000001405CD210 var_1F0 = qword ptr -1F0h -.text:00000001405CD210 var_1E8 = qword ptr -1E8h -.text:00000001405CD210 var_1E0 = dword ptr -1E0h -.text:00000001405CD210 var_1DC = word ptr -1DCh -.text:00000001405CD210 var_1DA = word ptr -1DAh -.text:00000001405CD210 var_1D8 = qword ptr -1D8h -.text:00000001405CD210 var_1D0 = byte ptr -1D0h -.text:00000001405CD210 var_1C8 = qword ptr -1C8h -.text:00000001405CD210 var_1B0 = dword ptr -1B0h -.text:00000001405CD210 var_1AC = dword ptr -1ACh -.text:00000001405CD210 var_1A8 = dword ptr -1A8h -.text:00000001405CD210 var_1A4 = dword ptr -1A4h -.text:00000001405CD210 var_1A0 = dword ptr -1A0h -.text:00000001405CD210 var_160 = dword ptr -160h -.text:00000001405CD210 var_15C = dword ptr -15Ch -.text:00000001405CD210 var_140 = dword ptr -140h -.text:00000001405CD210 var_138 = dword ptr -138h -.text:00000001405CD210 var_130 = byte ptr -130h -.text:00000001405CD210 var_C0 = byte ptr -0C0h -.text:00000001405CD210 var_50 = qword ptr -50h -.text:00000001405CD210 var_38 = qword ptr -38h -.text:00000001405CD210 var_30 = qword ptr -30h -.text:00000001405CD210 var_28 = qword ptr -28h -.text:00000001405CD210 var_20 = qword ptr -20h -.text:00000001405CD210 senderActorId = dword ptr 30h -.text:00000001405CD210 isLocal = byte ptr 38h -.text:00000001405CD210 -.text:00000001405CD210 ; __unwind { // __GSHandlerCheck -.text:00000001405CD210 push rbp -.text:00000001405CD212 push rdi -.text:00000001405CD213 push r14 -.text:00000001405CD215 push r15 -.text:00000001405CD217 lea rbp, [rsp-128h] -.text:00000001405CD21F sub rsp, 228h -.text:00000001405CD226 mov rax, cs:__security_cookie -.text:00000001405CD22D xor rax, rsp -.text:00000001405CD230 mov [rbp+140h+var_50], rax -.text:00000001405CD237 xor r10b, r10b -.text:00000001405CD23A mov [rsp+240h+var_1F8], rcx -.text:00000001405CD23F xor eax, eax -.text:00000001405CD241 mov r11, r9 -.text:00000001405CD244 mov r14, r8 -.text:00000001405CD247 mov r9d, eax -.text:00000001405CD24A movzx r15d, dx -.text:00000001405CD24E lea r8, [rcx+0C10h] -.text:00000001405CD255 mov rdi, rcx - */ - - protected override void Setup64Bit(SigScanner sig) { - //PrintMessage = sig.ScanText("4055 57 41 ?? 41 ?? 488DAC24D8FEFFFF 4881EC28020000 488B05???????? 4833C4 488985F0000000 4532D2 48894C2448"); LAST PART FOR 5.1??? - PrintMessage = - sig.ScanText( - "4055 53 56 4154 4157 48 8d ac 24 ?? ?? ?? ?? 48 81 ec 20 02 00 00 48 8b 05" - ); - //PrintMessage = sig.ScanText("4055 57 41 ?? 41 ?? 488DAC24E8FEFFFF 4881EC18020000 488B05???????? 4833C4 488985E0000000 4532D2 48894C2438"); old - - //PrintMessage = sig.ScanText("40 55 57 41 56 41 57 48 8D AC 24 D8 FE FF FF 48 81 EC 28 02 00 00 48 8B 05 63 47 4A 01 48 33 C4 48 89 85 F0 00 00 00 45 32 D2 48 89 4C 24 48 33"); - - //PopulateItemLinkObject = sig.ScanText("48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 FA F2 B0 FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); - - //PopulateItemLinkObject = sig.ScanText( "48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 ?? ?? B0 FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); 5.0 - PopulateItemLinkObject = sig.ScanText("48 89 5C 24 08 57 48 83 EC 20 80 7A 06 00 48 8B DA 48 8B F9 74 14 48 8B CA E8 32 03 00 00 48 8B C8 E8 ?? ?? ?? FF 8B C8 EB 1D 0F B6 42 14 8B 4A"); - } - } -} diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs deleted file mode 100644 index 370341300..000000000 --- a/Dalamud/Game/Internal/Gui/GameGui.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Dalamud.Game.Chat; -using Dalamud.Hooking; -using Serilog; - -namespace Dalamud.Game.Internal.Gui { - public sealed class GameGui : IDisposable { - private GameGuiAddressResolver Address { get; } - - public ChatGui Chat { get; private set; } - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr SetGlobalBgmDelegate(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6); - - private readonly Hook setGlobalBgmHook; - - public GameGui(IntPtr baseAddress, SigScanner scanner, Dalamud dalamud) { - Address = new GameGuiAddressResolver(baseAddress); - Address.Setup(scanner); - - Log.Verbose("===== G A M E G U I ====="); - - Log.Verbose("GameGuiManager address {Address}", Address.BaseAddress); - Log.Verbose("SetGlobalBgm address {Address}", Address.SetGlobalBgm); - - Chat = new ChatGui(Address.ChatManager, scanner, dalamud); - - this.setGlobalBgmHook = - new Hook(Address.SetGlobalBgm, - new SetGlobalBgmDelegate(HandleSetGlobalBgmDetour), - this); - } - - private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) { - var retVal = this.setGlobalBgmHook.Original(bgmKey, a2, a3, a4, a5, a6); - - Log.Verbose("SetGlobalBgm: {0} {1} {2} {3} {4} {5} -> {6}", bgmKey, a2, a3, a4, a5, a6, retVal); - - return retVal; - } - - public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0); - - public void Enable() { - Chat.Enable(); - this.setGlobalBgmHook.Enable(); - } - - public void Dispose() { - Chat.Dispose(); - this.setGlobalBgmHook.Dispose(); - } - } -} diff --git a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs deleted file mode 100644 index c0127e8d4..000000000 --- a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Serilog; - -namespace Dalamud.Game.Internal.Gui { - public sealed class GameGuiAddressResolver : BaseAddressResolver { - public IntPtr BaseAddress { get; private set; } - - public IntPtr ChatManager { get; private set; } - - public IntPtr SetGlobalBgm { get; private set; } - - public GameGuiAddressResolver(IntPtr baseAddress) { - BaseAddress = baseAddress; - } - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr GetChatManagerDelegate(IntPtr guiManager); - - protected override void SetupInternal(SigScanner scanner) { - // Xiv__UiManager__GetChatManager 000 lea rax, [rcx+13E0h] - // Xiv__UiManager__GetChatManager+7 000 retn - ChatManager = BaseAddress + 0x13E0; - } - - protected override void Setup64Bit(SigScanner sig) { - //SetGlobalBgm = sig.ScanText("4C 8B 15 ?? ?? ?? ?? 4D 85 D2 74 58 41 83 7A ?? ?? 76 51 4D 8B 92 ?? ?? ?? ?? 0F B6 44 24 ?? 49 81 C2 ?? ?? ?? ?? 66 41 89 4A ?? 33 C9 41 88 52 30 41 89 4A 14 66 41 89 4A ?? 41 88 42 12 49 89 4A 38 41 89 4A 40 49 89 4A 48 41 38 4A 30 74 14 8B 44 24 28 41 89 42 40 45 89 42 38"); - SetGlobalBgm = sig.ScanText("4C 8B 15 ?? ?? ?? ?? 4D 85 D2 74 58"); - } - } -} diff --git a/Dalamud/Game/Internal/Gui/TargetManager.cs b/Dalamud/Game/Internal/Gui/TargetManager.cs deleted file mode 100644 index 202684581..000000000 --- a/Dalamud/Game/Internal/Gui/TargetManager.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Dalamud.Game.ClientState; -using Dalamud.Game.ClientState.Actors.Types; -using Dalamud.Game.ClientState.Structs.JobGauge; -using Dalamud.Hooking; -using Serilog; -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace Dalamud.Game.Internal.Gui { - public class TargetManager { - public delegate IntPtr GetTargetDelegate(IntPtr manager); - - private Hook getTargetHook; - - private TargetManagerAddressResolver Address; - - public unsafe TargetManager(Dalamud dalamud, SigScanner scanner) { - this.Address = new TargetManagerAddressResolver(); - this.Address.Setup(scanner); - - Log.Verbose("===== T A R G E T M A N A G E R ====="); - Log.Verbose("GetTarget address {GetTarget}", Address.GetTarget); - - this.getTargetHook = new Hook(this.Address.GetTarget, new GetTargetDelegate(GetTargetDetour), this); - } - - public void Enable() { - this.getTargetHook.Enable(); - } - - public void Dispose() { - this.getTargetHook.Dispose(); - } - - private IntPtr GetTargetDetour(IntPtr manager) - { - try { - var res = this.getTargetHook.Original(manager); - - var test = Marshal.ReadInt32(res); - - Log.Debug($"GetTargetDetour {manager.ToInt64():X} -> RET: {res:X}"); - - return res; - } - catch (Exception ex) - { - Log.Error(ex, "Exception GetTargetDetour hook."); - return this.getTargetHook.Original(manager); - } - } - } -} diff --git a/Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs b/Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs deleted file mode 100644 index 137742bc0..000000000 --- a/Dalamud/Game/Internal/Gui/TargetManagerAddressResolver.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Internal.Gui { - class TargetManagerAddressResolver : BaseAddressResolver { - public IntPtr GetTarget { get; private set; } - - protected override void Setup64Bit(SigScanner sig) { - this.GetTarget = sig.ScanText("40 57 48 83 EC 40 48 8B F9 48 8B 49 08 48 8B 01 FF 50 40 66 83 B8 CA 81 00 00 00 74 33 48 8B 4F 08 48 8B 01 FF 50 40 66 83 B8 CA 81 00 00 04 74"); - } - } -} diff --git a/Dalamud/Game/Internal/Libc/LibcFunction.cs b/Dalamud/Game/Internal/Libc/LibcFunction.cs deleted file mode 100644 index 9ea4dc6a8..000000000 --- a/Dalamud/Game/Internal/Libc/LibcFunction.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Serilog; - -namespace Dalamud.Game.Internal.Libc { - public sealed class LibcFunction { - // TODO: prolly callconv is not okay in x86 - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr StdStringFromCStringDelegate(IntPtr pStdString, [MarshalAs(UnmanagedType.LPArray)]byte[] content, IntPtr size); - - // TODO: prolly callconv is not okay in x86 - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr StdStringDeallocateDelegate(IntPtr address); - - private LibcFunctionAddressResolver Address { get; } - - private readonly StdStringFromCStringDelegate stdStringCtorCString; - private readonly StdStringDeallocateDelegate stdStringDeallocate; - - public LibcFunction(SigScanner scanner) { - Address = new LibcFunctionAddressResolver(); - Address.Setup(scanner); - - this.stdStringCtorCString = Marshal.GetDelegateForFunctionPointer(Address.StdStringFromCstring); - this.stdStringDeallocate = Marshal.GetDelegateForFunctionPointer(Address.StdStringDeallocate); - } - - public OwnedStdString NewString(byte[] content) { - // While 0x70 bytes in the memory should be enough in DX11 version, - // I don't trust my analysis so we're just going to allocate almost two times more than that. - var pString = Marshal.AllocHGlobal(256); - - // Initialize a string - var npos = new IntPtr(0xFFFFFFFF); // assumed to be -1 (0xFFFFFFFF in x86, 0xFFFFFFFF_FFFFFFFF in amd64) - var pReallocString = this.stdStringCtorCString(pString, content, npos); - - //Log.Verbose("Prev: {Prev} Now: {Now}", pString, pReallocString); - - return new OwnedStdString(pReallocString, DeallocateStdString); - } - - private void DeallocateStdString(IntPtr address) { - this.stdStringDeallocate(address); - } - } -} diff --git a/Dalamud/Game/Internal/Libc/LibcFunctionAddressResolver.cs b/Dalamud/Game/Internal/Libc/LibcFunctionAddressResolver.cs deleted file mode 100644 index aeaefa595..000000000 --- a/Dalamud/Game/Internal/Libc/LibcFunctionAddressResolver.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Security.Policy; - -namespace Dalamud.Game.Internal.Libc { - public sealed class LibcFunctionAddressResolver : BaseAddressResolver { - private delegate IntPtr StringFromCString(); - - public IntPtr StdStringFromCstring { get; private set; } - public IntPtr StdStringDeallocate { get; private set; } - - protected override void Setup64Bit(SigScanner sig) { - StdStringFromCstring = sig.ScanText("48895C2408 4889742410 57 4883EC20 488D4122 66C741200101 488901 498BD8"); - StdStringDeallocate = sig.ScanText("80792100 7512 488B5108 41B833000000 488B09 E9??????00 C3"); - } - } -} diff --git a/Dalamud/Game/Internal/Libc/OwnedStdString.cs b/Dalamud/Game/Internal/Libc/OwnedStdString.cs deleted file mode 100644 index ea68d8f91..000000000 --- a/Dalamud/Game/Internal/Libc/OwnedStdString.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Runtime.InteropServices; -using Serilog; - -namespace Dalamud.Game.Internal.Libc { - public sealed class OwnedStdString : IDisposable { - internal delegate void DeallocatorDelegate(IntPtr address); - - // ala. the drop flag - private bool isDisposed; - - private readonly DeallocatorDelegate dealloc; - - public IntPtr Address { get; private set; } - - /// - /// Construct a wrapper around std::string - /// - /// - /// Violating any of these might cause an undefined hehaviour. - /// 1. This function takes the ownership of the address. - /// 2. A memory pointed by address argument is assumed to be allocated by Marshal.AllocHGlobal thus will try to call Marshal.FreeHGlobal on the address. - /// 3. std::string object pointed by address must be initialized before calling this function. - /// - /// - /// A deallocator function. - /// - internal OwnedStdString(IntPtr address, DeallocatorDelegate dealloc) { - Address = address; - this.dealloc = dealloc; - } - - ~OwnedStdString() { - ReleaseUnmanagedResources(); - } - - private void ReleaseUnmanagedResources() { - if (Address == IntPtr.Zero) { - // Something got seriously fucked. - throw new AccessViolationException(); - } - - // Deallocate inner string first - this.dealloc(Address); - - // Free the heap - Marshal.FreeHGlobal(Address); - - // Better safe (running on a nullptr) than sorry. (running on a dangling pointer) - Address = IntPtr.Zero; - } - - public void Dispose() { - // No double free plz, kthx. - if (this.isDisposed) { - return; - } - this.isDisposed = true; - - ReleaseUnmanagedResources(); - GC.SuppressFinalize(this); - } - - public StdString Read() { - return StdString.ReadFromPointer(Address); - } - } -} diff --git a/Dalamud/Game/Internal/Libc/StdString.cs b/Dalamud/Game/Internal/Libc/StdString.cs deleted file mode 100644 index c91b26690..000000000 --- a/Dalamud/Game/Internal/Libc/StdString.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Linq; -using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; -using System.Text; -using Newtonsoft.Json.Linq; -using Serilog; - -namespace Dalamud.Game.Internal.Libc { - /// - /// Interation with std::string - /// - public class StdString { - public static StdString ReadFromPointer(IntPtr cstring) { - unsafe { - if (cstring == IntPtr.Zero) { - throw new ArgumentNullException(nameof(cstring)); - } - - var innerAddress = Marshal.ReadIntPtr(cstring); - if (innerAddress == IntPtr.Zero) { - throw new NullReferenceException("Inner reference to the cstring is null."); - } - - var count = 0; - - // Count the number of chars. String is assumed to be zero-terminated. - while (Marshal.ReadByte(innerAddress + count) != 0) { - count += 1; - } - - // raw copy, as UTF8 string conversion is lossy - var rawData = new byte[count]; - Marshal.Copy(innerAddress, rawData, 0, count); - - return new StdString { - RawData = rawData, - Value = Encoding.UTF8.GetString(rawData) - }; - } - } - - private StdString() { } - - public string Value { get; private set; } - - public byte[] RawData { get; set; } - } -} diff --git a/Dalamud/Game/Internal/Network/GameNetwork.cs b/Dalamud/Game/Internal/Network/GameNetwork.cs deleted file mode 100644 index eb59ce2a5..000000000 --- a/Dalamud/Game/Internal/Network/GameNetwork.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Dalamud.Hooking; -using Serilog; - -namespace Dalamud.Game.Internal.Network { - public sealed class GameNetwork : IDisposable { - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate void ProcessZonePacketDelegate(IntPtr a, IntPtr b, IntPtr dataPtr); - - private readonly Hook processZonePacketHook; - - private GameNetworkAddressResolver Address { get; } - private IntPtr baseAddress; - - public delegate void OnZonePacketDelegate(IntPtr dataPtr); - - public OnZonePacketDelegate OnZonePacket; - - private readonly Dalamud dalamud; - - private readonly Queue zoneInjectQueue = new Queue(); - - public GameNetwork(Dalamud dalamud, SigScanner scanner) { - this.dalamud = dalamud; - Address = new GameNetworkAddressResolver(); - Address.Setup(scanner); - - Log.Verbose("===== G A M E N E T W O R K ====="); - Log.Verbose("ProcessZonePacket address {ProcessZonePacket}", Address.ProcessZonePacket); - - this.processZonePacketHook = - new Hook(Address.ProcessZonePacket, - new ProcessZonePacketDelegate(ProcessZonePacketDetour), - this); - } - - public void Enable() { - this.processZonePacketHook.Enable(); - } - - public void Dispose() { - this.processZonePacketHook.Dispose(); - } - - private void ProcessZonePacketDetour(IntPtr a, IntPtr b, IntPtr dataPtr) { - this.baseAddress = a; - - // Call events - this.OnZonePacket?.Invoke(dataPtr); - - try { - this.processZonePacketHook.Original(a, b, dataPtr); - } catch (Exception ex) { - string header; - try { - var data = new byte[32]; - Marshal.Copy(dataPtr, data, 0, 32); - header = BitConverter.ToString(data); - } catch (Exception) { - header = "failed"; - } - - Log.Error(ex, "Exception on ProcessZonePacket hook. Header: " + header); - - this.processZonePacketHook.Original(a, b, dataPtr); - } - } - -#if DEBUG - public void InjectZoneProtoPacket(byte[] data) { - this.zoneInjectQueue.Enqueue(data); - } - - private void InjectActorControl(short cat, int param1) { - var packetData = new byte[] { - 0x14, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x17, 0x7C, 0xC5, 0x5D, 0x00, 0x00, 0x00, 0x00, - 0x05, 0x00, 0x48, 0xB2, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x43, 0x7F, 0x00, 0x00 - }; - - BitConverter.GetBytes((short) cat).CopyTo(packetData, 0x10); - - BitConverter.GetBytes((UInt32) param1).CopyTo(packetData, 0x14); - - InjectZoneProtoPacket(packetData); - } -#endif - - /// - /// Process a chat queue. - /// - public void UpdateQueue(Framework framework) - { - while (this.zoneInjectQueue.Count > 0) - { - var packetData = this.zoneInjectQueue.Dequeue(); - - var unmanagedPacketData = Marshal.AllocHGlobal(packetData.Length); - Marshal.Copy(packetData, 0, unmanagedPacketData, packetData.Length); - - if (this.baseAddress != IntPtr.Zero) { - this.processZonePacketHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData); - } - - Marshal.FreeHGlobal(unmanagedPacketData); - } - } - } -} diff --git a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs deleted file mode 100644 index 09ad99ebb..000000000 --- a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Dalamud.Game.Internal.Network { - public sealed class GameNetworkAddressResolver : BaseAddressResolver { - public IntPtr ProcessZonePacket { get; private set; } - - protected override void Setup64Bit(SigScanner sig) { - //ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05"); - //ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 73 FF 0F B7 57 02 8D 42 ?? 3D ?? ?? 00 00 0F 87 60 01 00 00 4C 8D 05"); - ProcessZonePacket = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0"); - } - } -} diff --git a/Dalamud/Game/Internal/Resource/ResourceManager.cs b/Dalamud/Game/Internal/Resource/ResourceManager.cs deleted file mode 100644 index b12e1b8a6..000000000 --- a/Dalamud/Game/Internal/Resource/ResourceManager.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Game.Internal.Libc; -using Dalamud.Hooking; -using Serilog; - -namespace Dalamud.Game.Internal.File -{ - public class ResourceManager { - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr GetResourceAsyncDelegate(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6, byte a7); - private readonly Hook getResourceAsyncHook; - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr GetResourceSyncDelegate(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6); - private readonly Hook getResourceSyncHook; - - private ResourceManagerAddressResolver Address { get; } - private readonly Dalamud dalamud; - - class ResourceHandleHookInfo { - public string Path { get; set; } - public Stream DetourFile { get; set; } - } - - private Dictionary resourceHookMap = new Dictionary(); - - public ResourceManager(Dalamud dalamud, SigScanner scanner) { - this.dalamud = dalamud; - Address = new ResourceManagerAddressResolver(); - Address.Setup(scanner); - - Log.Verbose("===== R E S O U R C E M A N A G E R ====="); - Log.Verbose("GetResourceAsync address {GetResourceAsync}", Address.GetResourceAsync); - Log.Verbose("GetResourceSync address {GetResourceSync}", Address.GetResourceSync); - - this.getResourceAsyncHook = - new Hook(Address.GetResourceAsync, - new GetResourceAsyncDelegate(GetResourceAsyncDetour), - this); - - this.getResourceSyncHook = - new Hook(Address.GetResourceSync, - new GetResourceSyncDelegate(GetResourceSyncDetour), - this); - - } - - public void Enable() { - this.getResourceAsyncHook.Enable(); - this.getResourceSyncHook.Enable(); - } - - public void Dispose() { - this.getResourceAsyncHook.Dispose(); - this.getResourceSyncHook.Dispose(); - } - - private IntPtr GetResourceAsyncDetour(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6, byte a7) { - - try { - var path = Marshal.PtrToStringAnsi(a5); - - var resourceHandle = this.getResourceAsyncHook.Original(manager, a2, a3, a4, IntPtr.Zero, a6, a7); - //var resourceHandle = IntPtr.Zero; - - Log.Verbose("GetResourceAsync CALL - this:{0} a2:{1} a3:{2} a4:{3} a5:{4} a6:{5} a7:{6} => RET:{7}", manager, a2, a3, a4, a5, a6, a7, resourceHandle); - - Log.Verbose($"->{path}"); - - HandleGetResourceHookAcquire(resourceHandle, path); - - return resourceHandle; - } catch (Exception ex) { - Log.Error(ex, "Exception on ReadResourceAsync hook."); - - return this.getResourceAsyncHook.Original(manager, a2, a3, a4, a5, a6, a7); - } - } - - private void DumpMem(IntPtr address, int len = 512) { - if (address == IntPtr.Zero) - return; - - var data = new byte[len]; - Marshal.Copy(address, data, 0, len); - - Log.Verbose($"MEMDMP at {address.ToInt64():X} for {len:X}\n{Util.ByteArrayToHex(data)}"); - } - - private IntPtr GetResourceSyncDetour(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr a5, IntPtr a6) { - - try { - var resourceHandle = this.getResourceSyncHook.Original(manager, a2, a3, a4, a5, a6); - - Log.Verbose("GetResourceSync CALL - this:{0} a2:{1} a3:{2} a4:{3} a5:{4} a6:{5} => RET:{6}", manager, a2, a3, a4, a5, a6, resourceHandle); - - var path = Marshal.PtrToStringAnsi(a5); - - Log.Verbose($"->{path}"); - - HandleGetResourceHookAcquire(resourceHandle, path); - - return resourceHandle; - } catch (Exception ex) { - Log.Error(ex, "Exception on ReadResourceSync hook."); - - return this.getResourceSyncHook.Original(manager, a2, a3, a4, a5, a6); - } - } - - private void HandleGetResourceHookAcquire(IntPtr handlePtr, string path) { - if (FilePathHasInvalidChars(path)) - return; - - if (this.resourceHookMap.ContainsKey(handlePtr)) { - Log.Verbose($"-> Handle {handlePtr.ToInt64():X}({path}) was cached!"); - return; - } - - var hookInfo = new ResourceHandleHookInfo { - Path = path - }; - - var hookPath = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "ResourceHook", path); - - if (System.IO.File.Exists(hookPath)) { - hookInfo.DetourFile = new FileStream(hookPath, FileMode.Open); - Log.Verbose("-> Added resource hook detour at {0}", hookPath); - } - - this.resourceHookMap.Add(handlePtr, hookInfo); - } - - public static bool FilePathHasInvalidChars(string path) - { - - return (!string.IsNullOrEmpty(path) && path.IndexOfAny(System.IO.Path.GetInvalidPathChars()) >= 0); - } - } -} diff --git a/Dalamud/Game/Internal/Resource/ResourceManagerAddressResolver.cs b/Dalamud/Game/Internal/Resource/ResourceManagerAddressResolver.cs deleted file mode 100644 index 2be49b4ac..000000000 --- a/Dalamud/Game/Internal/Resource/ResourceManagerAddressResolver.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game.Internal.File -{ - class ResourceManagerAddressResolver : BaseAddressResolver - { - public IntPtr GetResourceAsync { get; private set; } - public IntPtr GetResourceSync { get; private set; } - - protected override void Setup64Bit(SigScanner sig) { - GetResourceAsync = sig.ScanText("48 89 5C 24 08 48 89 54 24 10 57 48 83 EC 20 B8 03 00 00 00 48 8B F9 86 82 A1 00 00 00 48 8B 5C 24 38 B8 01 00 00 00 87 83 90 00 00 00 85 C0 74"); - GetResourceSync = sig.ScanText("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 30 48 8B F9 49 8B E9 48 83 C1 30 4D 8B F0 4C 8B EA FF 15 CE F6"); - //ReadResourceSync = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05"); - } - } -} diff --git a/Dalamud/Game/Network/MarketBoardItemRequest.cs b/Dalamud/Game/Network/MarketBoardItemRequest.cs deleted file mode 100644 index 7ec9afe90..000000000 --- a/Dalamud/Game/Network/MarketBoardItemRequest.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Collections.Generic; -using Dalamud.Game.Network.Structures; - -namespace Dalamud.Game.Network { - internal class MarketBoardItemRequest { - public uint CatalogId { get; set; } - public byte AmountToArrive { get; set; } - - public List Listings { get; set; } - public List History { get; set; } - - public int ListingsRequestId { get; set; } = -1; - - public bool IsDone => Listings.Count == AmountToArrive && History.Count != 0; - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/IMarketBoardUploader.cs b/Dalamud/Game/Network/MarketBoardUploaders/IMarketBoardUploader.cs deleted file mode 100644 index cd675d865..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/IMarketBoardUploader.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Dalamud.Game.Network.Structures; - -namespace Dalamud.Game.Network.MarketBoardUploaders { - internal interface IMarketBoardUploader { - void Upload(MarketBoardItemRequest itemRequest); - void UploadTax(MarketTaxRates taxRates); - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryEntry.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryEntry.cs deleted file mode 100644 index c3b5a4146..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryEntry.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Newtonsoft.Json; - -namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis { - internal class UniversalisHistoryEntry { - [JsonProperty("hq")] - public bool Hq { get; set; } - - [JsonProperty("pricePerUnit")] - public uint PricePerUnit { get; set; } - - [JsonProperty("quantity")] - public uint Quantity { get; set; } - - [JsonProperty("buyerName")] - public string BuyerName { get; set; } - - [JsonProperty("onMannequin")] - public bool OnMannequin { get; set; } - - [JsonProperty("sellerID")] - public ulong SellerId { get; set; } - - [JsonProperty("buyerID")] - public ulong BuyerId { get; set; } - - [JsonProperty("timestamp")] - public long Timestamp { get; set; } - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryUploadRequest.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryUploadRequest.cs deleted file mode 100644 index 51bcbacb8..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryUploadRequest.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis { - internal class UniversalisHistoryUploadRequest { - [JsonProperty("worldID")] - public int WorldId { get; set; } - - [JsonProperty("itemID")] - public uint ItemId { get; set; } - - [JsonProperty("entries")] - public List Entries { get; set; } - - [JsonProperty("uploaderID")] - public ulong UploaderId { get; set; } - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsEntry.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsEntry.cs deleted file mode 100644 index 336e6773c..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsEntry.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis { - internal class UniversalisItemListingsEntry { - [JsonProperty("listingID")] - public ulong ListingId { get; set; } - - [JsonProperty("hq")] - public bool Hq { get; set; } - - [JsonProperty("pricePerUnit")] - public uint PricePerUnit { get; set; } - - [JsonProperty("quantity")] - public uint Quantity { get; set; } - - [JsonProperty("retainerName")] - public string RetainerName { get; set; } - - [JsonProperty("retainerID")] - public ulong RetainerId { get; set; } - - [JsonProperty("creatorName")] - public string CreatorName { get; set; } - - [JsonProperty("onMannequin")] - public bool OnMannequin { get; set; } - - [JsonProperty("sellerID")] - public ulong SellerId { get; set; } - - [JsonProperty("creatorID")] - public ulong CreatorId { get; set; } - - [JsonProperty("stainID")] - public int StainId { get; set; } - - [JsonProperty("retainerCity")] - public int RetainerCity { get; set; } - - [JsonProperty("lastReviewTime")] - public long LastReviewTime { get; set; } - - [JsonProperty("materia")] - public List Materia { get; set; } - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsUploadRequest.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsUploadRequest.cs deleted file mode 100644 index e07525f13..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsUploadRequest.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis { - internal class UniversalisItemListingsUploadRequest { - [JsonProperty("worldID")] - public int WorldId { get; set; } - - [JsonProperty("itemID")] - public uint ItemId { get; set; } - - [JsonProperty("listings")] - public List Listings { get; set; } - - [JsonProperty("uploaderID")] - public ulong UploaderId { get; set; } - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemMateria.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemMateria.cs deleted file mode 100644 index 93742b84b..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemMateria.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Newtonsoft.Json; - -namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis { - internal class UniversalisItemMateria { - [JsonProperty("slotID")] - public int SlotId { get; set; } - - [JsonProperty("materiaID")] - public int MateriaId { get; set; } - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs deleted file mode 100644 index 83c657b14..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Net; -using Dalamud.Game.Network.MarketBoardUploaders; -using Dalamud.Game.Network.MarketBoardUploaders.Universalis; -using Dalamud.Game.Network.Structures; -using Newtonsoft.Json; -using Serilog; - -namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders { - internal class UniversalisMarketBoardUploader : IMarketBoardUploader { - private const string ApiBase = "https://universalis.app"; - - //private const string ApiBase = "https://127.0.0.1:443"; - private const string ApiKey = "GGD6RdSfGyRiHM5WDnAo0Nj9Nv7aC5NDhMj3BebT"; - - private readonly Dalamud dalamud; - - public UniversalisMarketBoardUploader(Dalamud dalamud) { - this.dalamud = dalamud; - } - - public void Upload(MarketBoardItemRequest request) { - using (var client = new WebClient()) { - client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); - - Log.Verbose("Starting Universalis upload."); - var uploader = this.dalamud.ClientState.LocalContentId; - - var listingsRequestObject = new UniversalisItemListingsUploadRequest(); - listingsRequestObject.WorldId = this.dalamud.ClientState.LocalPlayer.CurrentWorld.Id; - listingsRequestObject.UploaderId = uploader; - listingsRequestObject.ItemId = request.CatalogId; - - listingsRequestObject.Listings = new List(); - foreach (var marketBoardItemListing in request.Listings) { - var universalisListing = new UniversalisItemListingsEntry { - Hq = marketBoardItemListing.IsHq, - SellerId = marketBoardItemListing.RetainerOwnerId, - RetainerName = marketBoardItemListing.RetainerName, - RetainerId = marketBoardItemListing.RetainerId, - CreatorId = marketBoardItemListing.ArtisanId, - CreatorName = marketBoardItemListing.PlayerName, - OnMannequin = marketBoardItemListing.OnMannequin, - LastReviewTime = ((DateTimeOffset) marketBoardItemListing.LastReviewTime).ToUnixTimeSeconds(), - PricePerUnit = marketBoardItemListing.PricePerUnit, - Quantity = marketBoardItemListing.ItemQuantity, - RetainerCity = marketBoardItemListing.RetainerCityId - }; - - universalisListing.Materia = new List(); - foreach (var itemMateria in marketBoardItemListing.Materia) - universalisListing.Materia.Add(new UniversalisItemMateria { - MateriaId = itemMateria.MateriaId, - SlotId = itemMateria.Index - }); - - listingsRequestObject.Listings.Add(universalisListing); - } - - var upload = JsonConvert.SerializeObject(listingsRequestObject); - client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", upload); - Log.Verbose(upload); - - var historyRequestObject = new UniversalisHistoryUploadRequest(); - historyRequestObject.WorldId = this.dalamud.ClientState.LocalPlayer.CurrentWorld.Id; - historyRequestObject.UploaderId = uploader; - historyRequestObject.ItemId = request.CatalogId; - - historyRequestObject.Entries = new List(); - foreach (var marketBoardHistoryListing in request.History) - historyRequestObject.Entries.Add(new UniversalisHistoryEntry { - BuyerName = marketBoardHistoryListing.BuyerName, - Hq = marketBoardHistoryListing.IsHq, - OnMannequin = marketBoardHistoryListing.OnMannequin, - PricePerUnit = marketBoardHistoryListing.SalePrice, - Quantity = marketBoardHistoryListing.Quantity, - Timestamp = ((DateTimeOffset) marketBoardHistoryListing.PurchaseTime).ToUnixTimeSeconds() - }); - - client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); - - var historyUpload = JsonConvert.SerializeObject(historyRequestObject); - client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload); - Log.Verbose(historyUpload); - - Log.Verbose("Universalis data upload for item#{0} completed.", request.CatalogId); - } - } - - public void UploadTax(MarketTaxRates taxRates) { - using (var client = new WebClient()) - { - var taxRatesRequest = new UniversalisTaxUploadRequest(); - taxRatesRequest.WorldId = this.dalamud.ClientState.LocalPlayer.CurrentWorld.Id; - taxRatesRequest.UploaderId = this.dalamud.ClientState.LocalContentId; - - taxRatesRequest.TaxData = new UniversalisTaxData { - LimsaLominsa = taxRates.LimsaLominsaTax, - Gridania = taxRates.GridaniaTax, - Uldah = taxRates.UldahTax, - Ishgard = taxRates.IshgardTax, - Kugane = taxRates.KuganeTax, - Crystarium = taxRates.CrystariumTax - }; - - client.Headers.Add(HttpRequestHeader.ContentType, "application/json"); - - var historyUpload = JsonConvert.SerializeObject(taxRatesRequest); - client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload); - Log.Verbose(historyUpload); - - Log.Verbose("Universalis tax upload completed."); - } - } - } -} diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxUploadRequest.cs b/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxUploadRequest.cs deleted file mode 100644 index 0e142c17c..000000000 --- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxUploadRequest.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; - -namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis -{ - class UniversalisTaxUploadRequest - { - [JsonProperty("uploaderID")] - public ulong UploaderId { get; set; } - - [JsonProperty("worldID")] - public int WorldId { get; set; } - - [JsonProperty("marketTaxRates")] - public UniversalisTaxData TaxData { get; set; } - } - - class UniversalisTaxData { - [JsonProperty("limsaLominsa")] - public uint LimsaLominsa { get; set; } - - [JsonProperty("gridania")] - public uint Gridania { get; set; } - - [JsonProperty("uldah")] - public uint Uldah { get; set; } - - [JsonProperty("ishgard")] - public uint Ishgard { get; set; } - - [JsonProperty("kugane")] - public uint Kugane { get; set; } - - [JsonProperty("crystarium")] - public uint Crystarium { get; set; } - } -} diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs deleted file mode 100644 index b5b073075..000000000 --- a/Dalamud/Game/Network/NetworkHandlers.cs +++ /dev/null @@ -1,246 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Threading.Tasks; -using Dalamud.Data.TransientSheet; -using Dalamud.Game.Network.MarketBoardUploaders; -using Dalamud.Game.Network.Structures; -using Dalamud.Game.Network.Universalis.MarketBoardUploaders; -using Lumina.Excel; -using Newtonsoft.Json.Linq; -using Serilog; - -namespace Dalamud.Game.Network { - public class NetworkHandlers { - private readonly Dalamud dalamud; - - private readonly List marketBoardRequests = new List(); - - private readonly bool optOutMbUploads; - private readonly IMarketBoardUploader uploader; - - private byte[] lastPreferredRole; - - public delegate Task CfPop(ContentFinderCondition cfc); - public event CfPop ProcessCfPop; - - public NetworkHandlers(Dalamud dalamud, bool optOutMbUploads) { - this.dalamud = dalamud; - this.optOutMbUploads = optOutMbUploads; - - this.uploader = new UniversalisMarketBoardUploader(dalamud); - - dalamud.Framework.Network.OnZonePacket += OnZonePacket; - - } - - private void OnZonePacket(IntPtr dataPtr) { - if (!this.dalamud.Data.IsDataReady) - return; - - var opCode = (ushort) Marshal.ReadInt16(dataPtr, 2); - - if (opCode == this.dalamud.Data.ServerOpCodes["CfNotifyPop"]) { - var data = new byte[64]; - Marshal.Copy(dataPtr, data, 0, 64); - - var notifyType = data[16]; - var contentFinderConditionId = BitConverter.ToUInt16(data, 36); - - if (notifyType != 3 || contentFinderConditionId == 0) - return; - - var contentFinderCondition = this.dalamud.Data.GetExcelSheet().GetRow(contentFinderConditionId); - - if (contentFinderCondition == null) - { - Log.Error("CFC key {0} not in lumina data.", contentFinderConditionId); - return; - } - - Task.Run(async () => { - this.dalamud.Framework.Gui.Chat.Print($"Duty pop: " + contentFinderCondition.Name); - - await this.ProcessCfPop?.Invoke(contentFinderCondition); - - }); - - return; - } - - if (opCode == this.dalamud.Data.ServerOpCodes["CfPreferredRole"]) { - if (this.dalamud.Configuration.PreferredRoleReminders == null) - return; - - var data = new byte[64]; - Marshal.Copy(dataPtr, data, 0, 32); - - if (this.lastPreferredRole == null) { - this.lastPreferredRole = data; - return; - } - - Task.Run(async () => { - for (var rouletteIndex = 1; rouletteIndex < 11; rouletteIndex++) { - var currentRoleKey = data[16 + rouletteIndex]; - var prevRoleKey = this.lastPreferredRole[16 + rouletteIndex]; - - Log.Verbose("CfPreferredRole: {0} - {1} => {2}", rouletteIndex, prevRoleKey, currentRoleKey); - - if (currentRoleKey != prevRoleKey) { - var rouletteName = rouletteIndex switch { - 1 => "Duty Roulette: Leveling", - 2 => "Duty Roulette: Level 50/60/70 Dungeons", - 3 => "Duty Roulette: Main Scenario", - 4 => "Duty Roulette: Guildhests", - 5 => "Duty Roulette: Expert", - 6 => "Duty Roulette: Trials", - 8 => "Duty Roulette: Mentor", - 9 => "Duty Roulette: Alliance Raids", - 10 => "Duty Roulette: Normal Raids", - _ => "Unknown ContentRoulette" - }; - - var prevRoleName = RoleKeyToPreferredRole(prevRoleKey); - var currentRoleName = RoleKeyToPreferredRole(currentRoleKey); - - if (!this.dalamud.Configuration.PreferredRoleReminders.TryGetValue(rouletteIndex, out var roleToCheck)) - return; - - if (roleToCheck == DalamudConfiguration.PreferredRole.All || currentRoleName != roleToCheck) - return; - - this.dalamud.Framework.Gui.Chat.Print($"Roulette bonus for {rouletteName} changed: {prevRoleName} => {currentRoleName}"); - - if (this.dalamud.BotManager.IsConnected) - await this.dalamud.BotManager.ProcessCfPreferredRoleChange(rouletteName, prevRoleName.ToString(), currentRoleName.ToString()); - } - } - - this.lastPreferredRole = data; - }); - return; - } - - if (!this.optOutMbUploads) { - if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) { - var catalogId = (uint) Marshal.ReadInt32(dataPtr + 0x10); - var amount = Marshal.ReadByte(dataPtr + 0x1B); - - this.marketBoardRequests.Add(new MarketBoardItemRequest { - CatalogId = catalogId, - AmountToArrive = amount, - Listings = new List(), - History = new List() - }); - - Log.Verbose($"NEW MB REQUEST START: item#{catalogId} amount#{amount}"); - return; - } - - if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardOfferings"]) { - var listing = MarketBoardCurrentOfferings.Read(dataPtr + 0x10); - - var request = - this.marketBoardRequests.LastOrDefault( - r => r.CatalogId == listing.ItemListings[0].CatalogId && !r.IsDone); - - if (request == null) { - Log.Error( - $"Market Board data arrived without a corresponding request: item#{listing.ItemListings[0].CatalogId}"); - return; - } - - if (request.Listings.Count + listing.ItemListings.Count > request.AmountToArrive) { - Log.Error( - $"Too many Market Board listings received for request: {request.Listings.Count + listing.ItemListings.Count} > {request.AmountToArrive} item#{listing.ItemListings[0].CatalogId}"); - return; - } - - if (request.ListingsRequestId != -1 && request.ListingsRequestId != listing.RequestId) { - Log.Error( - $"Non-matching RequestIds for Market Board data request: {request.ListingsRequestId}, {listing.RequestId}"); - return; - } - - if (request.ListingsRequestId == -1 && request.Listings.Count > 0) { - Log.Error( - $"Market Board data request sequence break: {request.ListingsRequestId}, {request.Listings.Count}"); - return; - } - - if (request.ListingsRequestId == -1) { - request.ListingsRequestId = listing.RequestId; - Log.Verbose($"First Market Board packet in sequence: {listing.RequestId}"); - } - - request.Listings.AddRange(listing.ItemListings); - - Log.Verbose("Added {0} ItemListings to request#{1}, now {2}/{3}, item#{4}", - listing.ItemListings.Count, request.ListingsRequestId, request.Listings.Count, - request.AmountToArrive, request.CatalogId); - - if (request.IsDone) { - Log.Verbose("Market Board request finished, starting upload: request#{0} item#{1} amount#{2}", - request.ListingsRequestId, request.CatalogId, request.AmountToArrive); - try { - Task.Run(() => this.uploader.Upload(request)); - } catch (Exception ex) { - Log.Error(ex, "Market Board data upload failed."); - } - } - - return; - } - - if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardHistory"]) { - var listing = MarketBoardHistory.Read(dataPtr + 0x10); - - var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId); - - if (request == null) { - Log.Error( - $"Market Board data arrived without a corresponding request: item#{listing.CatalogId}"); - return; - } - - if (request.ListingsRequestId != -1) { - Log.Error( - $"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}"); - return; - } - - request.History.AddRange(listing.HistoryListings); - - Log.Verbose("Added history for item#{0}", listing.CatalogId); - } - - if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"]) - { - var taxes = MarketTaxRates.Read(dataPtr + 0x10); - - Log.Verbose("MarketTaxRates: limsa#{0} grid#{1} uldah#{2} ish#{3} kugane#{4} cr#{5}", - taxes.LimsaLominsaTax, taxes.GridaniaTax, taxes.UldahTax, taxes.IshgardTax, taxes.KuganeTax, taxes.CrystariumTax); - try - { - Task.Run(() => this.uploader.UploadTax(taxes)); - } - catch (Exception ex) - { - Log.Error(ex, "Market Board data upload failed."); - } - } - } - } - - private DalamudConfiguration.PreferredRole RoleKeyToPreferredRole(int key) => key switch - { - 1 => DalamudConfiguration.PreferredRole.Tank, - 2 => DalamudConfiguration.PreferredRole.Dps, - 3 => DalamudConfiguration.PreferredRole.Dps, - 4 => DalamudConfiguration.PreferredRole.Healer, - _ => DalamudConfiguration.PreferredRole.None - }; - } -} diff --git a/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs b/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs deleted file mode 100644 index 7d9f72cc8..000000000 --- a/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace Dalamud.Game.Network.Structures -{ - public class MarketBoardCurrentOfferings - { - public List ItemListings; - - public int ListingIndexEnd; - public int ListingIndexStart; - public int RequestId; - - public static unsafe MarketBoardCurrentOfferings Read(IntPtr dataPtr) - { - var output = new MarketBoardCurrentOfferings(); - - using (var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544)) - { - using (var reader = new BinaryReader(stream)) - { - output.ItemListings = new List(); - - for (var i = 0; i < 10; i++) - { - var listingEntry = new MarketBoardItemListing(); - - listingEntry.ListingId = reader.ReadUInt64(); - listingEntry.RetainerId = reader.ReadUInt64(); - listingEntry.RetainerOwnerId = reader.ReadUInt64(); - listingEntry.ArtisanId = reader.ReadUInt64(); - listingEntry.PricePerUnit = reader.ReadUInt32(); - listingEntry.TotalTax = reader.ReadUInt32(); - listingEntry.ItemQuantity = reader.ReadUInt32(); - listingEntry.CatalogId = reader.ReadUInt32(); - listingEntry.LastReviewTime = DateTimeOffset.UtcNow.AddSeconds(-reader.ReadUInt16()).DateTime; - - reader.ReadUInt16(); // container - reader.ReadUInt32(); // slot - reader.ReadUInt16(); // durability - reader.ReadUInt16(); // spiritbond - - listingEntry.Materia = new List(); - - for (var materiaIndex = 0; materiaIndex < 5; materiaIndex++) - { - var materiaVal = reader.ReadUInt16(); - - var materiaEntry = new MarketBoardItemListing.ItemMateria(); - materiaEntry.MateriaId = (materiaVal & 0xFF0) >> 4; - materiaEntry.Index = materiaVal & 0xF; - - if (materiaEntry.MateriaId != 0) - listingEntry.Materia.Add(materiaEntry); - } - - reader.ReadUInt16(); - reader.ReadUInt32(); - - listingEntry.RetainerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd('\u0000'); - listingEntry.PlayerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd('\u0000'); - listingEntry.IsHq = reader.ReadBoolean(); - listingEntry.MateriaCount = reader.ReadByte(); - listingEntry.OnMannequin = reader.ReadBoolean(); - listingEntry.RetainerCityId = reader.ReadByte(); - listingEntry.StainId = reader.ReadUInt16(); - - reader.ReadUInt16(); - reader.ReadUInt32(); - - if (listingEntry.CatalogId != 0) - output.ItemListings.Add(listingEntry); - } - - output.ListingIndexEnd = reader.ReadByte(); - output.ListingIndexStart = reader.ReadByte(); - output.RequestId = reader.ReadUInt16(); - } - } - - return output; - } - - public class MarketBoardItemListing - { - public ulong ArtisanId; - public uint CatalogId; - public bool IsHq; - public uint ItemQuantity; - public DateTime LastReviewTime; - public ulong ListingId; - - public List Materia; - public int MateriaCount; - public bool OnMannequin; - public string PlayerName; - public uint PricePerUnit; - public int RetainerCityId; - public ulong RetainerId; - - public string RetainerName; - public ulong RetainerOwnerId; - public int StainId; - public uint TotalTax; - - public class ItemMateria - { - public int Index; - public int MateriaId; - } - } - } -} diff --git a/Dalamud/Game/Network/Structures/MarketBoardHistory.cs b/Dalamud/Game/Network/Structures/MarketBoardHistory.cs deleted file mode 100644 index c96b4a0e0..000000000 --- a/Dalamud/Game/Network/Structures/MarketBoardHistory.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; - -namespace Dalamud.Game.Network.Structures { - public class MarketBoardHistory { - public uint CatalogId; - public uint CatalogId2; - - public List HistoryListings; - - public static unsafe MarketBoardHistory Read(IntPtr dataPtr) { - var output = new MarketBoardHistory(); - - using (var stream = new UnmanagedMemoryStream((byte*) dataPtr.ToPointer(), 1544)) { - using (var reader = new BinaryReader(stream)) { - output.CatalogId = reader.ReadUInt32(); - output.CatalogId2 = reader.ReadUInt32(); - - output.HistoryListings = new List(); - - for (var i = 0; i < 10; i++) { - var listingEntry = new MarketBoardHistoryListing(); - - listingEntry.SalePrice = reader.ReadUInt32(); - listingEntry.PurchaseTime = DateTimeOffset.FromUnixTimeSeconds(reader.ReadUInt32()).UtcDateTime; - listingEntry.Quantity = reader.ReadUInt32(); - listingEntry.IsHq = reader.ReadBoolean(); - - reader.ReadBoolean(); - - listingEntry.OnMannequin = reader.ReadBoolean(); - listingEntry.BuyerName = Encoding.UTF8.GetString(reader.ReadBytes(33)).TrimEnd('\u0000'); - listingEntry.CatalogId = reader.ReadUInt32(); - - if (listingEntry.CatalogId != 0) - output.HistoryListings.Add(listingEntry); - } - } - } - - return output; - } - - public class MarketBoardHistoryListing { - public string BuyerName; - - public uint CatalogId; - public bool IsHq; - public bool OnMannequin; - public DateTime PurchaseTime; - public uint Quantity; - public uint SalePrice; - } - } -} diff --git a/Dalamud/Game/Network/Structures/MarketTaxRate.cs b/Dalamud/Game/Network/Structures/MarketTaxRate.cs deleted file mode 100644 index b0ce2772c..000000000 --- a/Dalamud/Game/Network/Structures/MarketTaxRate.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Text; - -namespace Dalamud.Game.Network.Structures -{ - public class MarketTaxRates - { - public uint LimsaLominsaTax; - public uint GridaniaTax; - public uint UldahTax; - public uint IshgardTax; - public uint KuganeTax; - public uint CrystariumTax; - - - public static unsafe MarketTaxRates Read(IntPtr dataPtr) - { - var output = new MarketTaxRates(); - - using (var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544)) - { - using (var reader = new BinaryReader(stream)) - { - stream.Position += 8; - - output.LimsaLominsaTax = reader.ReadUInt32(); - output.GridaniaTax = reader.ReadUInt32(); - output.UldahTax = reader.ReadUInt32(); - output.IshgardTax = reader.ReadUInt32(); - output.KuganeTax = reader.ReadUInt32(); - output.CrystariumTax = reader.ReadUInt32(); - } - } - - return output; - } - } -} diff --git a/Dalamud/Game/Network/WinSockHandlers.cs b/Dalamud/Game/Network/WinSockHandlers.cs deleted file mode 100644 index f2d9d9706..000000000 --- a/Dalamud/Game/Network/WinSockHandlers.cs +++ /dev/null @@ -1,55 +0,0 @@ -using Dalamud.Hooking; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Sockets; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Game -{ - internal sealed class WinSockHandlers : IDisposable - { - [UnmanagedFunctionPointer(CallingConvention.Winapi)] - private delegate IntPtr SocketDelegate(int af, int type, int protocol); - private Hook ws2SocketHook; - - [DllImport("ws2_32.dll", CallingConvention = CallingConvention.Winapi)] - private static extern int setsockopt(IntPtr socket, SocketOptionLevel level, SocketOptionName optName, ref IntPtr optVal, int optLen); - - public WinSockHandlers() { - this.ws2SocketHook = Hook.FromSymbol("ws2_32.dll", "socket", new SocketDelegate(OnSocket)); - this.ws2SocketHook.Enable(); - } - - private IntPtr OnSocket(int af, int type, int protocol) - { - var socket = this.ws2SocketHook.Original(af, type, protocol); - - // IPPROTO_TCP - if (type == 1) - { - // INVALID_SOCKET - if (socket != new IntPtr(-1)) - { - // In case you're not aware of it: (albeit you should) - // https://linux.die.net/man/7/tcp - // https://assets.extrahop.com/whitepapers/TCP-Optimization-Guide-by-ExtraHop.pdf - var value = new IntPtr(1); - setsockopt(socket, SocketOptionLevel.Tcp, SocketOptionName.NoDelay, ref value, 4); - - // Enable tcp_quickack option. This option is undocumented in MSDN but it is supported in Windows 7 and onwards. - value = new IntPtr(1); - setsockopt(socket, SocketOptionLevel.Tcp, (SocketOptionName)12, ref value, 4); - } - } - - return socket; - } - - public void Dispose() { - ws2SocketHook.Dispose(); - } - } -} diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs deleted file mode 100644 index 1d4fc7df8..000000000 --- a/Dalamud/Game/SigScanner.cs +++ /dev/null @@ -1,251 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using Serilog; - -namespace Dalamud.Game { - /// - /// A SigScanner facilitates searching for memory signatures in a given ProcessModule. - /// - public sealed class SigScanner : IDisposable { - /// - /// Set up the SigScanner. - /// - /// The ProcessModule to be used for scanning - /// Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks. - public SigScanner(ProcessModule module, bool doCopy = false) { - Module = module; - Is32BitProcess = !Environment.Is64BitProcess; - IsCopy = doCopy; - - // Limit the search space to .text section. - SetupSearchSpace(module); - - if (IsCopy) - SetupCopiedSegments(); - - Log.Verbose("Module base: {Address}", TextSectionBase); - Log.Verbose("Module size: {Size}", TextSectionSize); - } - - /// - /// If the search on this module is performed on a copy. - /// - public bool IsCopy { get; private set; } - - /// - /// If the ProcessModule is 32-bit. - /// - public bool Is32BitProcess { get; } - - /// - /// The base address of the search area. When copied, this will be the address of the copy. - /// - public IntPtr SearchBase => IsCopy ? this.moduleCopyPtr : Module.BaseAddress; - - /// - /// The base address of the .text section search area. - /// - public IntPtr TextSectionBase => new IntPtr(SearchBase.ToInt64() + TextSectionOffset); - /// - /// The offset of the .text section from the base of the module. - /// - public long TextSectionOffset { get; private set; } - /// - /// The size of the text section. - /// - public int TextSectionSize { get; private set; } - - /// - /// The base address of the .data section search area. - /// - public IntPtr DataSectionBase => new IntPtr(SearchBase.ToInt64() + DataSectionOffset); - /// - /// The offset of the .data section from the base of the module. - /// - public long DataSectionOffset { get; private set; } - /// - /// The size of the .data section. - /// - public int DataSectionSize { get; private set; } - - /// - /// The ProcessModule on which the search is performed. - /// - public ProcessModule Module { get; } - - private IntPtr TextSectionTop => TextSectionBase + TextSectionSize; - - private void SetupSearchSpace(ProcessModule module) { - var baseAddress = module.BaseAddress; - - // We don't want to read all of IMAGE_DOS_HEADER or IMAGE_NT_HEADER stuff so we cheat here. - var ntNewOffset = Marshal.ReadInt32(baseAddress, 0x3C); - var ntHeader = baseAddress + ntNewOffset; - - // IMAGE_NT_HEADER - var fileHeader = ntHeader + 4; - var numSections = Marshal.ReadInt16(ntHeader, 6); - - // IMAGE_OPTIONAL_HEADER - var optionalHeader = fileHeader + 20; - - IntPtr sectionHeader; - if (Is32BitProcess) // IMAGE_OPTIONAL_HEADER32 - sectionHeader = optionalHeader + 224; - else // IMAGE_OPTIONAL_HEADER64 - sectionHeader = optionalHeader + 240; - - // IMAGE_SECTION_HEADER - var sectionCursor = sectionHeader; - for (var i = 0; i < numSections; i++) { - var sectionName = Marshal.ReadInt64(sectionCursor); - - // .text - switch (sectionName) { - case 0x747865742E: // .text - TextSectionOffset = Marshal.ReadInt32(sectionCursor, 12); - TextSectionSize = Marshal.ReadInt32(sectionCursor, 8); - break; - case 0x617461642E: // .data - DataSectionOffset = Marshal.ReadInt32(sectionCursor, 12); - DataSectionSize = Marshal.ReadInt32(sectionCursor, 8); - break; - } - - sectionCursor += 40; - } - } - - private IntPtr moduleCopyPtr; - private long moduleCopyOffset; - - private unsafe void SetupCopiedSegments() { - Log.Verbose("module copy START"); - // .text - this.moduleCopyPtr = Marshal.AllocHGlobal(Module.ModuleMemorySize); - Log.Verbose($"Alloc: {this.moduleCopyPtr.ToInt64():x}"); - Buffer.MemoryCopy(Module.BaseAddress.ToPointer(), this.moduleCopyPtr.ToPointer(), Module.ModuleMemorySize, - Module.ModuleMemorySize); - - this.moduleCopyOffset = this.moduleCopyPtr.ToInt64() - Module.BaseAddress.ToInt64(); - - Log.Verbose("copy OK!"); - } - - /// - /// Free the memory of the copied module search area on object disposal, if applicable. - /// - public void Dispose() { - Marshal.FreeHGlobal(this.moduleCopyPtr); - } - - /// - /// Scan for a byte signature in the .text section. - /// - /// The signature. - /// The real offset of the found signature. - public IntPtr ScanText(string signature) { - var mBase = IsCopy ? this.moduleCopyPtr : TextSectionBase; - - var scanRet = Scan(mBase, TextSectionSize, signature); - - if (IsCopy) - scanRet = new IntPtr(scanRet.ToInt64() - this.moduleCopyOffset); - - return scanRet; - } - - /// - /// Scan for a byte signature in the .data section. - /// - /// The signature. - /// The real offset of the found signature. - public IntPtr ScanData(string signature) { - var scanRet = Scan(DataSectionBase, DataSectionSize, signature); - - if (IsCopy) - scanRet = new IntPtr(scanRet.ToInt64() - this.moduleCopyOffset); - - return scanRet; - } - - /// - /// Scan for a byte signature in the whole module search area. - /// - /// The signature. - /// The real offset of the found signature. - public IntPtr ScanModule(string signature) { - var scanRet = Scan(SearchBase, Module.ModuleMemorySize, signature); - - if (IsCopy) - scanRet = new IntPtr(scanRet.ToInt64() - this.moduleCopyOffset); - - return scanRet; - } - - public IntPtr Scan(IntPtr baseAddress, int size, string signature) { - var needle = SigToNeedle(signature); - - unsafe { - var pCursor = (byte*) baseAddress.ToPointer(); - var pTop = (byte*) (baseAddress + size - needle.Length); - while (pCursor < pTop) { - if (IsMatch(pCursor, needle)) return (IntPtr) pCursor; - - // Advance an offset - pCursor += 1; - } - } - - throw new KeyNotFoundException($"Can't find a signature of {signature}"); - } - - public IntPtr ResolveRelativeAddress(IntPtr nextInstAddr, int relOffset) { - if (Is32BitProcess) throw new NotSupportedException("32 bit is not supported."); - - return nextInstAddr + relOffset; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private unsafe bool IsMatch(byte* pCursor, byte?[] needle) { - for (var i = 0; i < needle.Length; i++) { - var expected = needle[i]; - if (expected == null) continue; - - var actual = *(pCursor + i); - if (expected != actual) return false; - } - - return true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private byte?[] SigToNeedle(string signature) { - // Strip all whitespaces - signature = signature.Replace(" ", ""); - - if (signature.Length % 2 != 0) - throw new ArgumentException("Signature without whitespaces must be divisible by two.", - nameof(signature)); - - var needleLength = signature.Length / 2; - var needle = new byte?[needleLength]; - - for (var i = 0; i < needleLength; i++) { - var hexString = signature.Substring(i * 2, 2); - if (hexString == "??" || hexString == "**") { - needle[i] = null; - continue; - } - - needle[i] = byte.Parse(hexString, NumberStyles.AllowHexSpecifier); - } - - return needle; - } - } -} diff --git a/Dalamud/Hooking/Hook.cs b/Dalamud/Hooking/Hook.cs deleted file mode 100644 index c6311a79d..000000000 --- a/Dalamud/Hooking/Hook.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using EasyHook; - -namespace Dalamud.Hooking { - /// - /// Manages a hook which can be used to intercept a call to native function. - /// This class is basically a thin wrapper around the LocalHook type to provide helper functions. - /// - /// Delegate type to represents a function prototype. This must be the same prototype as original function do. - public sealed class Hook : IDisposable where T : Delegate { - private bool isDisposed; - - private readonly IntPtr address; - - private readonly T original; - - private readonly LocalHook hookInfo; - - /// - /// A memory address of the target function. - /// - /// Hook is already disposed. - public IntPtr Address { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { - CheckDisposed(); - return this.address; - } - } - - /// - /// A delegate function that can be used to call the actual function as if function is not hooked yet. - /// - /// - /// Hook is already disposed. - public T Original { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get { - CheckDisposed(); - return this.original; - } - } - - - /// - /// Creates a hook. Hooking address is inferred by calling to GetProcAddress() function. Hook is not activated until Enable() method is called. - /// - /// A name of the module currently loaded in the memory. (e.g. ws2_32.dll) - /// A name of the exported function name (e.g. send) - /// Callback function. Delegate must have a same original function prototype. - /// A callback object which can be accessed within the detour. - /// - public static Hook FromSymbol(string moduleName, string exportName, Delegate detour, object callbackParam = null) { - // Get a function address from the symbol name. - var address = LocalHook.GetProcAddress(moduleName, exportName); - - return new Hook(address, detour, callbackParam); - } - - /// - /// Createss a hook. Hook is not activated until Enable() method is called. - /// - /// A memory address to install a hook. - /// Callback function. Delegate must have a same original function prototype. - /// A callback object which can be accessed within the detour. - public Hook(IntPtr address, Delegate detour, object callbackParam = null) { - this.hookInfo = LocalHook.Create(address, detour, callbackParam); // Installs a hook here - this.address = address; - this.original = Marshal.GetDelegateForFunctionPointer(this.hookInfo.HookBypassAddress); - } - - /// - /// Remove a hook from the current process. - /// - public void Dispose() { - if (this.isDisposed) { - return; - } - - this.hookInfo.Dispose(); - - this.isDisposed = true; - } - - /// - /// Starts intercepting a call to the function. - /// - public void Enable() { - CheckDisposed(); - - this.hookInfo.ThreadACL.SetExclusiveACL(null); - } - - /// - /// Stops intercepting a call to the function. - /// - public void Disable() { - CheckDisposed(); - - this.hookInfo.ThreadACL.SetInclusiveACL(null); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CheckDisposed() { - if (this.isDisposed) { - throw new ObjectDisposedException("Hook is already disposed."); - } - } - } -} diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs deleted file mode 100644 index 6290cbb40..000000000 --- a/Dalamud/Interface/DalamudDataWindow.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Data; -using ImGuiNET; -using Newtonsoft.Json; - -namespace Dalamud.Interface -{ - class DalamudDataWindow { - private DataManager dataMgr; - - private bool wasReady; - private string serverOpString; - private string cfcString = "N/A"; - - private int currentKind; - - public DalamudDataWindow(DataManager dataMgr) { - this.dataMgr = dataMgr; - - Load(); - } - - private void Load() { - if (this.dataMgr.IsDataReady) - { - this.serverOpString = JsonConvert.SerializeObject(this.dataMgr.ServerOpCodes, Formatting.Indented); - this.wasReady = true; - } - } - - public bool Draw() - { - ImGui.SetNextWindowSize(new Vector2(500, 500), ImGuiCond.Always); - - var isOpen = true; - - if (!ImGui.Begin("Dalamud Data", ref isOpen, ImGuiWindowFlags.NoCollapse)) - { - ImGui.End(); - return false; - } - - // Main window - if (ImGui.Button("Force Reload")) - Load(); - ImGui.SameLine(); - var copy = ImGui.Button("Copy all"); - ImGui.SameLine(); - ImGui.Combo("Data kind", ref currentKind, new[] {"ServerOpCode", "ContentFinderCondition"}, 2); - - ImGui.BeginChild("scrolling", new Vector2(0, 0), false, ImGuiWindowFlags.HorizontalScrollbar); - - if (copy) - ImGui.LogToClipboard(); - - ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); - - if (this.wasReady) { - switch (currentKind) { - case 0: ImGui.TextUnformatted(this.serverOpString); - break; - case 1: ImGui.TextUnformatted(this.cfcString); - break; - } - } else { - ImGui.TextUnformatted("Data not ready."); - } - - ImGui.PopStyleVar(); - - ImGui.EndChild(); - ImGui.End(); - - return isOpen; - } - } -} diff --git a/Dalamud/Interface/DalamudLogWindow.cs b/Dalamud/Interface/DalamudLogWindow.cs deleted file mode 100644 index 5d49c961a..000000000 --- a/Dalamud/Interface/DalamudLogWindow.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Text; -using System.Threading.Tasks; -using ImGuiNET; - -namespace Dalamud.Interface -{ - class DalamudLogWindow : IDisposable { - private bool autoScroll = true; - private string logText = string.Empty; - - public DalamudLogWindow() { - SerilogEventSink.Instance.OnLogLine += Serilog_OnLogLine; - } - - public void Dispose() { - SerilogEventSink.Instance.OnLogLine -= Serilog_OnLogLine; - } - - private void Serilog_OnLogLine(object sender, string e) - { - AddLog(e + "\n"); - } - - public void Clear() { - this.logText = string.Empty; - } - - public void AddLog(string line) { - this.logText += line; - } - - public bool Draw() { - ImGui.SetNextWindowSize(new Vector2(500, 400), ImGuiCond.FirstUseEver); - - var isOpen = true; - - if (!ImGui.Begin("Dalamud LOG", ref isOpen, ImGuiWindowFlags.NoCollapse)) - { - ImGui.End(); - return false; - } - - // Options menu - if (ImGui.BeginPopup("Options")) - { - ImGui.Checkbox("Auto-scroll", ref this.autoScroll); - ImGui.EndPopup(); - } - - // Main window - if (ImGui.Button("Options")) - ImGui.OpenPopup("Options"); - ImGui.SameLine(); - var clear = ImGui.Button("Clear"); - ImGui.SameLine(); - var copy = ImGui.Button("Copy"); - - ImGui.BeginChild("scrolling", new Vector2(0, 0), false, ImGuiWindowFlags.HorizontalScrollbar); - - if (clear) - Clear(); - if (copy) - ImGui.LogToClipboard(); - - ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(0, 0)); - - ImGui.TextUnformatted(this.logText); - - ImGui.PopStyleVar(); - - if (this.autoScroll && ImGui.GetScrollY() >= ImGui.GetScrollMaxY()) - ImGui.SetScrollHereY(1.0f); - - ImGui.EndChild(); - ImGui.End(); - - return isOpen; - } - } -} diff --git a/Dalamud/Interface/InterfaceManager.cs b/Dalamud/Interface/InterfaceManager.cs deleted file mode 100644 index 7c0c25bd7..000000000 --- a/Dalamud/Interface/InterfaceManager.cs +++ /dev/null @@ -1,210 +0,0 @@ -using System; -using System.IO; -using System.Numerics; -using System.Runtime.InteropServices; -using Dalamud.Game; -using Dalamud.Game.Internal.DXGI; -using Dalamud.Hooking; -using EasyHook; -using ImGuiNET; -using ImGuiScene; -using Serilog; - -// general dev notes, here because it's easiest -/* - * - Hooking ResizeBuffers seemed to be unnecessary, though I'm not sure why. Left out for now since it seems to work without it. - * - We may want to build our ImGui command list in a thread to keep it divorced from present. We'd still have to block in present to - * synchronize on the list and render it, but ideally the overall delay we add to present would then be shorter. This may cause minor - * timing issues with anything animated inside ImGui, but that is probably rare and may not even be noticeable. - * - Our hook is too low level to really work well with debugging, as we only have access to the 'real' dx objects and not any - * that have been hooked/wrapped by tools. - * - Might eventually want to render to a separate target and composite, especially with reshade etc in the mix. - */ - -namespace Dalamud.Interface -{ - public class InterfaceManager : IDisposable - { - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr PresentDelegate(IntPtr swapChain, uint syncInterval, uint presentFlags); - - private readonly Hook presentHook; - - private readonly Hook setCursorHook; - - [UnmanagedFunctionPointer(CallingConvention.ThisCall)] - private delegate IntPtr SetCursorDelegate(IntPtr hCursor); - - private ISwapChainAddressResolver Address { get; } - - private Dalamud dalamud; - private RawDX11Scene scene; - - /// - /// This event gets called by a plugin UiBuilder when read - /// - public event RawDX11Scene.BuildUIDelegate OnDraw; - - public InterfaceManager(Dalamud dalamud, SigScanner scanner) - { - this.dalamud = dalamud; - - try { - var sigResolver = new SwapChainSigResolver(); - sigResolver.Setup(scanner); - - Log.Verbose("Found SwapChain via signatures."); - - Address = sigResolver; - } catch (Exception ex) { - // The SigScanner method fails on wine/proton since DXGI is not a real DLL. We fall back to vtable to detect our Present function address. - Log.Error(ex, "Could not get SwapChain address via sig method, falling back to vtable..."); - - var vtableResolver = new SwapChainVtableResolver(); - vtableResolver.Setup(scanner); - - Log.Verbose("Found SwapChain via vtable."); - - Address = vtableResolver; - } - - var setCursorAddr = LocalHook.GetProcAddress("user32.dll", "SetCursor"); - - Log.Verbose("===== S W A P C H A I N ====="); - Log.Verbose("SetCursor address {SetCursor}", setCursorAddr); - Log.Verbose("Present address {Present}", Address.Present); - - this.setCursorHook = new Hook(setCursorAddr, new SetCursorDelegate(SetCursorDetour), this); - - this.presentHook = - new Hook(Address.Present, - new PresentDelegate(PresentDetour), - this); - } - - public void Enable() - { - this.setCursorHook.Enable(); - this.presentHook.Enable(); - } - - private void Disable() - { - this.setCursorHook.Disable(); - this.presentHook.Disable(); - } - - public void Dispose() - { - // HACK: this is usually called on a separate thread from PresentDetour (likely on a dedicated render thread) - // and if we aren't already disabled, disposing of the scene and hook can frequently crash due to the hook - // being disposed of in this thread while it is actively in use in the render thread. - // This is a terrible way to prevent issues, but should basically always work to ensure that all outstanding - // calls to PresentDetour have finished (and Disable means no new ones will start), before we try to cleanup - // So... not great, but much better than constantly crashing on unload - this.Disable(); - System.Threading.Thread.Sleep(100); - - this.scene.Dispose(); - this.presentHook.Dispose(); - } - - public TextureWrap LoadImage(string filePath) - { - try - { - return this.scene?.LoadImage(filePath) ?? null; - } - catch (Exception ex) - { - Log.Error(ex, $"Failed to load image from {filePath}"); - } - return null; - } - - public TextureWrap LoadImage(byte[] imageData) - { - try - { - return this.scene?.LoadImage(imageData) ?? null; - } - catch (Exception ex) - { - Log.Error(ex, "Failed to load image from memory"); - } - return null; - } - - private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags) - { - if (this.scene == null) - { - this.scene = new RawDX11Scene(swapChain); - this.scene.ImGuiIniPath = Path.Combine(Path.GetDirectoryName(this.dalamud.StartInfo.ConfigurationPath), "dalamudUI.ini"); - this.scene.OnBuildUI += Display; - - var fontPathJp = Path.Combine(Path.GetDirectoryName(typeof(InterfaceManager).Assembly.Location), "UIRes", "NotoSansCJKjp-Medium.otf"); - ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese()); - - ImGui.GetIO().Fonts.Build(); - - ImGui.GetStyle().GrabRounding = 3f; - ImGui.GetStyle().FrameRounding = 4f; - ImGui.GetStyle().WindowRounding = 4f; - ImGui.GetStyle().WindowBorderSize = 0f; - ImGui.GetStyle().WindowMenuButtonPosition = ImGuiDir.Right; - ImGui.GetStyle().ScrollbarSize = 16f; - - ImGui.GetStyle().Colors[(int) ImGuiCol.WindowBg] = new Vector4(0.06f, 0.06f, 0.06f, 0.87f); - ImGui.GetStyle().Colors[(int) ImGuiCol.FrameBg] = new Vector4(0.29f, 0.29f, 0.29f, 0.54f); - ImGui.GetStyle().Colors[(int) ImGuiCol.FrameBgHovered] = new Vector4(0.54f, 0.54f, 0.54f, 0.40f); - ImGui.GetStyle().Colors[(int) ImGuiCol.FrameBgActive] = new Vector4(0.64f, 0.64f, 0.64f, 0.67f); - ImGui.GetStyle().Colors[(int) ImGuiCol.TitleBgActive] = new Vector4(0.29f, 0.29f, 0.29f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.CheckMark] = new Vector4(0.86f, 0.86f, 0.86f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.SliderGrab] = new Vector4(0.54f, 0.54f, 0.54f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.SliderGrabActive] = new Vector4(0.67f, 0.67f, 0.67f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.Button] = new Vector4(0.71f, 0.71f, 0.71f, 0.40f); - ImGui.GetStyle().Colors[(int) ImGuiCol.ButtonHovered] = new Vector4(0.47f, 0.47f, 0.47f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.ButtonActive] = new Vector4(0.74f, 0.74f, 0.74f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.Header] = new Vector4(0.59f, 0.59f, 0.59f, 0.31f); - ImGui.GetStyle().Colors[(int) ImGuiCol.HeaderHovered] = new Vector4(0.50f, 0.50f, 0.50f, 0.80f); - ImGui.GetStyle().Colors[(int) ImGuiCol.HeaderActive] = new Vector4(0.60f, 0.60f, 0.60f, 1.00f); - ImGui.GetStyle().Colors[(int) ImGuiCol.ResizeGrip] = new Vector4(0.79f, 0.79f, 0.79f, 0.25f); - ImGui.GetStyle().Colors[(int) ImGuiCol.ResizeGripHovered] = new Vector4(0.78f, 0.78f, 0.78f, 0.67f); - ImGui.GetStyle().Colors[(int) ImGuiCol.ResizeGripActive] = new Vector4(0.88f, 0.88f, 0.88f, 0.95f); - ImGui.GetStyle().Colors[(int) ImGuiCol.Tab] = new Vector4(0.23f, 0.23f, 0.23f, 0.86f); - ImGui.GetStyle().Colors[(int) ImGuiCol.TabHovered] = new Vector4(0.71f, 0.71f, 0.71f, 0.80f); - ImGui.GetStyle().Colors[(int) ImGuiCol.TabActive] = new Vector4(0.36f, 0.36f, 0.36f, 1.00f); - } - - this.scene.Render(); - - return this.presentHook.Original(swapChain, syncInterval, presentFlags); - } - - // can't access imgui IO before first present call - private bool lastWantCapture = false; - - private IntPtr SetCursorDetour(IntPtr hCursor) { - if (this.lastWantCapture == true && (!scene?.IsImGuiCursor(hCursor) ?? false)) - return IntPtr.Zero; - - return this.setCursorHook.Original(hCursor); - } - - private void Display() - { - // this is more or less part of what reshade/etc do to avoid having to manually - // set the cursor inside the ui - // This will just tell ImGui to draw its own software cursor instead of using the hardware cursor - // The scene internally will handle hiding and showing the hardware (game) cursor - // If the player has the game software cursor enabled, we can't really do anything about that and - // they will see both cursors. - // Doing this here because it's somewhat application-specific behavior - //ImGui.GetIO().MouseDrawCursor = ImGui.GetIO().WantCaptureMouse; - this.lastWantCapture = ImGui.GetIO().WantCaptureMouse; - - OnDraw?.Invoke(); - } - } -} diff --git a/Dalamud/Interface/SerilogEventSink.cs b/Dalamud/Interface/SerilogEventSink.cs deleted file mode 100644 index 3e0f7d2d2..000000000 --- a/Dalamud/Interface/SerilogEventSink.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Serilog; -using Serilog.Configuration; -using Serilog.Core; -using Serilog.Events; - -namespace Dalamud.Interface -{ - public class SerilogEventSink : ILogEventSink - { - private readonly IFormatProvider _formatProvider; - - public static SerilogEventSink Instance; - - public event EventHandler OnLogLine; - - public SerilogEventSink(IFormatProvider formatProvider) - { - _formatProvider = formatProvider; - - Instance = this; - } - - public void Emit(LogEvent logEvent) - { - var message = $"[{DateTimeOffset.Now.ToString()}][{logEvent.Level}] {logEvent.RenderMessage(_formatProvider)}"; - - if (logEvent.Exception != null) - message += "\n" + logEvent.Exception; - - OnLogLine?.Invoke(this, message); - } - } - - public static class MySinkExtensions - { - public static LoggerConfiguration EventSink( - this LoggerSinkConfiguration loggerConfiguration, - IFormatProvider formatProvider = null) - { - return loggerConfiguration.Sink(new SerilogEventSink(formatProvider)); - } - } -} diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs deleted file mode 100644 index 0e689236d..000000000 --- a/Dalamud/Interface/UiBuilder.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using ImGuiNET; -using ImGuiScene; - -namespace Dalamud.Interface -{ - /// - /// This class represents the Dalamud UI that is drawn on top of the game. - /// It can be used to draw custom windows and overlays. - /// - public class UiBuilder : IDisposable { - private readonly string namespaceName; - - /// - /// The delegate that gets called when Dalamud is ready to draw your windows or overlays. - /// When it is called, you can use static ImGui calls. - /// - public event RawDX11Scene.BuildUIDelegate OnBuildUi; - - private readonly InterfaceManager interfaceManager; - - /// - /// Create a new UiBuilder and register it. You do not have to call this manually. - /// - /// The interface manager to register on. - /// The plugin namespace. - public UiBuilder(InterfaceManager interfaceManager, string namespaceName) { - this.namespaceName = namespaceName; - - this.interfaceManager = interfaceManager; - this.interfaceManager.OnDraw += OnDraw; - } - - /// - /// Unregister the UiBuilder. Do not call this in plugin code. - /// - public void Dispose() { - this.interfaceManager.OnDraw -= OnDraw; - } - - /// - /// Loads an image from the specified file. - /// - /// The full filepath to the image. - /// A object wrapping the created image. Use inside ImGui.Image() - public TextureWrap LoadImage(string filePath) => - this.interfaceManager.LoadImage(filePath); - - /// - /// Loads an image from a byte stream, such as a png downloaded into memory. - /// - /// A byte array containing the raw image data. - /// A object wrapping the created image. Use inside ImGui.Image() - public TextureWrap LoadImage(byte[] imageData) => - this.interfaceManager.LoadImage(imageData); - - private void OnDraw() { - ImGui.PushID(this.namespaceName); - OnBuildUi?.Invoke(); - ImGui.PopID(); - } - } -} diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs deleted file mode 100644 index d6d603346..000000000 --- a/Dalamud/Plugin/DalamudPluginInterface.cs +++ /dev/null @@ -1,147 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Configuration; -using Dalamud.Data; -using Dalamud.Game; -using Dalamud.Game.ClientState; -using Dalamud.Game.Command; -using Dalamud.Game.Internal; -using Dalamud.Game.Internal.Gui; -using Dalamud.Interface; - -namespace Dalamud.Plugin -{ - /// - /// This class acts as an interface to various objects needed to interact with Dalamud and the game. - /// - public class DalamudPluginInterface : IDisposable { - /// - /// The CommandManager object that allows you to add and remove custom chat commands. - /// - public readonly CommandManager CommandManager; - - /// - /// The ClientState object that allows you to access current client memory information like actors, territories, etc. - /// - public readonly ClientState ClientState; - - /// - /// The Framework object that allows you to interact with the client. - /// - public readonly Framework Framework; - - /// - /// A UiBuilder instance which allows you to draw UI into the game via ImGui draw calls. - /// - public readonly UiBuilder UiBuilder; - - /// - /// A SigScanner instance targeting the main module of the FFXIV process. - /// - public readonly SigScanner TargetModuleScanner; - - /// - /// A DataManager instance which allows you to access game data needed by the main dalamud features. - /// - public readonly DataManager Data; - - private readonly Dalamud dalamud; - private readonly string pluginName; - - /// - /// Set up the interface and populate all fields needed. - /// - /// - public DalamudPluginInterface(Dalamud dalamud, string pluginName) { - this.CommandManager = dalamud.CommandManager; - this.Framework = dalamud.Framework; - this.ClientState = dalamud.ClientState; - this.UiBuilder = new UiBuilder(dalamud.InterfaceManager, pluginName); - this.TargetModuleScanner = dalamud.SigScanner; - this.Data = dalamud.Data; - - this.dalamud = dalamud; - this.pluginName = pluginName; - } - - /// - /// Unregister your plugin and dispose all references. You have to call this when your IDalamudPlugin is disposed. - /// - public void Dispose() { - this.UiBuilder.Dispose(); - } - - /// - /// Save a plugin configuration(inheriting IPluginConfiguration). - /// - /// The current configuration. - public void SavePluginConfig(IPluginConfiguration currentConfig) { - if (this.dalamud.Configuration.PluginConfigurations == null) - this.dalamud.Configuration.PluginConfigurations = new Dictionary(); - - if (this.dalamud.Configuration.PluginConfigurations.ContainsKey(this.pluginName)) { - this.dalamud.Configuration.PluginConfigurations[this.pluginName] = currentConfig; - return; - } - - if (currentConfig == null) - return; - - this.dalamud.Configuration.PluginConfigurations.Add(this.pluginName, currentConfig); - this.dalamud.Configuration.Save(this.dalamud.StartInfo.ConfigurationPath); - } - - /// - /// Get a previously saved plugin configuration or null if none was saved before. - /// - /// A previously saved config or null if none was saved before. - public IPluginConfiguration GetPluginConfig() { - if (this.dalamud.Configuration.PluginConfigurations == null) - this.dalamud.Configuration.PluginConfigurations = new Dictionary(); - - if (!this.dalamud.Configuration.PluginConfigurations.ContainsKey(this.pluginName)) - return null; - - return this.dalamud.Configuration.PluginConfigurations[this.pluginName] as IPluginConfiguration; - } - - #region Logging - - /// - /// Log a templated message to the in-game debug log. - /// - /// The message template. - /// Values to log. - public void Log(string messageTemplate, params object[] values) { - Serilog.Log.Information(messageTemplate, values); - } - - /// - /// Log a templated error message to the in-game debug log. - /// - /// The message template. - /// Values to log. - public void LogError(string messageTemplate, params object[] values) - { - Serilog.Log.Error(messageTemplate, values); - } - - /// - /// Log a templated error message to the in-game debug log. - /// - /// The exception that caused the error. - /// The message template. - /// Values to log. - public void LogError(Exception exception, string messageTemplate, params object[] values) - { - Serilog.Log.Error(exception, messageTemplate, values); - } - - #endregion - } -} diff --git a/Dalamud/Plugin/Features/IHasConfigUi.cs b/Dalamud/Plugin/Features/IHasConfigUi.cs deleted file mode 100644 index 53e64ea98..000000000 --- a/Dalamud/Plugin/Features/IHasConfigUi.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using Dalamud.Interface; - -namespace Dalamud.Plugin.Features -{ - /// - /// This interface represents a Dalamud plugin that has a configuration UI which can be triggered. - /// - public interface IHasConfigUi : IHasUi - { - /// - /// An event handler that is fired when the plugin should show its configuration interface. - /// - EventHandler OpenConfigUi { get; } - } -} diff --git a/Dalamud/Plugin/Features/IHasUi.cs b/Dalamud/Plugin/Features/IHasUi.cs deleted file mode 100644 index afdb74df8..000000000 --- a/Dalamud/Plugin/Features/IHasUi.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Interface; - -namespace Dalamud.Plugin.Features -{ - /// - /// This interface represents a Dalamud plugin that has user interface which can be drawn. - /// - public interface IHasUi : IDalamudPlugin - { - /// - /// A function that gets called when Dalamud is ready to draw your UI. - /// - /// An object you can use to e.g. load images. - void Draw(UiBuilder uiBuilder); - } -} diff --git a/Dalamud/Plugin/IDalamudPlugin.cs b/Dalamud/Plugin/IDalamudPlugin.cs deleted file mode 100644 index 2e1cb67a8..000000000 --- a/Dalamud/Plugin/IDalamudPlugin.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Plugin -{ - /// - /// This interface represents a basic Dalamud plugin. All plugins have to implement this interface. - /// - public interface IDalamudPlugin : IDisposable - { - /// - /// The name of the plugin. - /// - string Name { get; } - - /// - /// Initializes a Dalamud plugin. - /// - /// The needed to access various Dalamud objects. - void Initialize(DalamudPluginInterface pluginInterface); - } -} diff --git a/Dalamud/Plugin/PluginDefinition.cs b/Dalamud/Plugin/PluginDefinition.cs deleted file mode 100644 index 29b373b75..000000000 --- a/Dalamud/Plugin/PluginDefinition.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud.Plugin -{ - public class PluginDefinition - { - public string Author { get; set; } - public string Name { get; set; } - public string InternalName { get; set; } - public string AssemblyVersion { get; set; } - public string Description { get; set; } - } -} diff --git a/Dalamud/Plugin/PluginInstallerWindow.cs b/Dalamud/Plugin/PluginInstallerWindow.cs deleted file mode 100644 index 6626239f7..000000000 --- a/Dalamud/Plugin/PluginInstallerWindow.cs +++ /dev/null @@ -1,231 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Numerics; -using System.Text; -using System.Threading.Tasks; -using Dalamud.Plugin.Features; -using ImGuiNET; -using Newtonsoft.Json; -using Serilog; - -namespace Dalamud.Plugin -{ - class PluginInstallerWindow { - private const string PluginRepoBaseUrl = "https://goaaats.github.io/DalamudPlugins/"; - - private PluginManager manager; - private string pluginDirectory; - private ReadOnlyCollection pluginMaster; - private bool errorModalDrawing = true; - private bool errorModalOnNextFrame = false; - - private enum PluginInstallStatus { - None, - InProgress, - Success, - Fail - } - - private PluginInstallStatus installStatus = PluginInstallStatus.None; - - private bool masterDownloadFailed = false; - - public PluginInstallerWindow(PluginManager manager, string pluginDirectory) { - this.manager = manager; - this.pluginDirectory = pluginDirectory; - Task.Run(CachePluginMaster).ContinueWith(t => { - this.masterDownloadFailed = this.masterDownloadFailed || t.IsFaulted; - this.errorModalDrawing = this.masterDownloadFailed; - this.errorModalOnNextFrame = this.masterDownloadFailed; - }); - } - - private void CachePluginMaster() { - try { - using var client = new WebClient(); - - var data = client.DownloadString(PluginRepoBaseUrl + "pluginmaster.json"); - - this.pluginMaster = JsonConvert.DeserializeObject>(data); - } catch { - this.masterDownloadFailed = true; - } - } - - private void InstallPlugin(PluginDefinition definition) { - try { - var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory, definition.InternalName, definition.AssemblyVersion)); - var dllFile = new FileInfo(Path.Combine(outputDir.FullName, $"{definition.InternalName}.dll")); - var disabledFile = new FileInfo(Path.Combine(outputDir.FullName, ".disabled")); - - if (dllFile.Exists) { - if (disabledFile.Exists) - disabledFile.Delete(); - - this.manager.LoadPluginFromAssembly(dllFile); - this.installStatus = PluginInstallStatus.Success; - return; - } - - if (outputDir.Exists) - outputDir.Delete(true); - outputDir.Create(); - - var path = Path.GetTempFileName(); - Log.Information("Downloading plugin to {0}", path); - using var client = new WebClient(); - client.DownloadFile(PluginRepoBaseUrl + $"/plugins/{definition.InternalName}/latest.zip", path); - - Log.Information("Extracting to {0}", outputDir); - - ZipFile.ExtractToDirectory(path, outputDir.FullName); - - this.installStatus = PluginInstallStatus.Success; - this.manager.LoadPluginFromAssembly(dllFile); - } catch (Exception e) { - Log.Error(e, "Plugin download failed hard."); - this.installStatus = PluginInstallStatus.Fail; - } - } - - public bool Draw() { - var windowOpen = true; - - ImGui.SetNextWindowSize(new Vector2(750, 520)); - - ImGui.Begin("Plugin Installer", ref windowOpen, - ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar); - - ImGui.Text("This window allows you install and remove in-game plugins."); - ImGui.Text("They are made by third-party developers."); - ImGui.Separator(); - - ImGui.BeginChild("scrolling", new Vector2(0, 400), true, ImGuiWindowFlags.HorizontalScrollbar); - - ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, new Vector2(1, 3)); - - if (this.pluginMaster == null) { - ImGui.Text("Loading plugins..."); - } else if (this.masterDownloadFailed) { - ImGui.Text("Download failed."); - } - else - { - foreach (var pluginDefinition in this.pluginMaster) - { - if (ImGui.CollapsingHeader(pluginDefinition.Name)) - { - ImGui.Indent(); - - ImGui.Text(pluginDefinition.Name); - ImGui.SameLine(); - ImGui.TextColored(new Vector4(0.5f, 0.5f, 0.5f, 1.0f), $" by {pluginDefinition.Author}"); - - ImGui.Text(pluginDefinition.Description); - - var isInstalled = this.manager.Plugins.Where(x=> x.Definition != null).Any( - x => x.Definition.InternalName == pluginDefinition.InternalName); - - if (!isInstalled) { - if (this.installStatus == PluginInstallStatus.InProgress) { - ImGui.Button($"Install in progress..."); - } else { - if (ImGui.Button($"Install v{pluginDefinition.AssemblyVersion}")) - { - this.installStatus = PluginInstallStatus.InProgress; - - Task.Run(() => InstallPlugin(pluginDefinition)).ContinueWith(t => { - this.installStatus = t.IsFaulted ? PluginInstallStatus.Fail : this.installStatus; - this.errorModalDrawing = this.installStatus == PluginInstallStatus.Fail; - this.errorModalOnNextFrame = this.installStatus == PluginInstallStatus.Fail; - }); - } - } - - } else { - var installedPlugin = this.manager.Plugins.Where(x => x.Definition != null).First( - x => x.Definition.InternalName == pluginDefinition.InternalName); - - if (ImGui.Button("Disable")) - { - this.manager.DisablePlugin(installedPlugin.Definition); - } - - if (installedPlugin.Plugin is IHasConfigUi v2Plugin && v2Plugin.OpenConfigUi != null) { - ImGui.SameLine(); - - if (ImGui.Button("Open Configuration")) - { - v2Plugin.OpenConfigUi?.Invoke(null, null); - } - } - } - - ImGui.Unindent(); - } - } - } - - ImGui.PopStyleVar(); - - ImGui.EndChild(); - - ImGui.Separator(); - - if (ImGui.Button("Remove All")) - { - - } - - ImGui.SameLine(); - - if (ImGui.Button("Open Plugin folder")) - { - - } - - ImGui.SameLine(); - - if (ImGui.Button("Close")) - { - windowOpen = false; - } - - if (ImGui.Button("test modal")) { - this.installStatus = PluginInstallStatus.Fail; - this.errorModalDrawing = true; - this.errorModalOnNextFrame = true; - } - - ImGui.Spacing(); - - if (ImGui.BeginPopupModal("Installer failed", ref this.errorModalDrawing, ImGuiWindowFlags.AlwaysAutoResize)) - { - ImGui.Text("The plugin installer ran into an issue."); - ImGui.Text("Please restart the game and report this error on our discord."); - - ImGui.Spacing(); - - if (ImGui.Button("OK", new Vector2(120, 40))) { ImGui.CloseCurrentPopup(); } - - ImGui.EndPopup(); - } - - if (this.errorModalOnNextFrame) { - ImGui.OpenPopup("Installer failed"); - this.errorModalOnNextFrame = false; - } - - - ImGui.End(); - - return windowOpen; - } - } -} diff --git a/Dalamud/Plugin/PluginManager.cs b/Dalamud/Plugin/PluginManager.cs deleted file mode 100644 index 70db2506a..000000000 --- a/Dalamud/Plugin/PluginManager.cs +++ /dev/null @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Newtonsoft.Json; -using Serilog; - -namespace Dalamud.Plugin -{ - public class PluginManager { - private readonly Dalamud dalamud; - private readonly string pluginDirectory; - - private readonly Type interfaceType = typeof(IDalamudPlugin); - - public readonly List<(IDalamudPlugin Plugin, PluginDefinition Definition)> Plugins = new List<(IDalamudPlugin plugin, PluginDefinition def)>(); - - public PluginManager(Dalamud dalamud, string pluginDirectory) { - this.dalamud = dalamud; - this.pluginDirectory = pluginDirectory; - } - - public void UnloadPlugins() { - if (this.Plugins == null) - return; - - for (var i = 0; i < this.Plugins.Count; i++) { - this.Plugins[i].Plugin.Dispose(); - } - - this.Plugins.Clear(); - } - - public void LoadPlugins() { - LoadPluginsAt(new DirectoryInfo(this.pluginDirectory)); - } - - public void DisablePlugin(PluginDefinition definition) { - var thisPlugin = this.Plugins.Where(x => x.Definition != null) - .First(x => x.Definition.InternalName == definition.InternalName); - - var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory, definition.InternalName, definition.AssemblyVersion)); - File.Create(Path.Combine(outputDir.FullName, ".disabled")); - - thisPlugin.Plugin.Dispose(); - - this.Plugins.Remove(thisPlugin); - } - - public void LoadPluginFromAssembly(FileInfo dllFile) { - Log.Information("Loading assembly at {0}", dllFile); - var assemblyName = AssemblyName.GetAssemblyName(dllFile.FullName); - var pluginAssembly = Assembly.Load(assemblyName); - - if (pluginAssembly != null) - { - Log.Information("Loading types for {0}", pluginAssembly.FullName); - var types = pluginAssembly.GetTypes(); - foreach (var type in types) - { - if (type.IsInterface || type.IsAbstract) - { - continue; - } - - if (type.GetInterface(interfaceType.FullName) != null) - { - var disabledFile = new FileInfo(Path.Combine(dllFile.Directory.FullName, ".disabled")); - - if (disabledFile.Exists) { - Log.Information("Plugin {0} is disabled.", dllFile.FullName); - return; - } - - var defJsonFile = new FileInfo(Path.Combine(dllFile.Directory.FullName, $"{Path.GetFileNameWithoutExtension(dllFile.Name)}.json")); - - PluginDefinition pluginDef = null; - if (defJsonFile.Exists) - { - Log.Information("Loading definition for plugin DLL {0}", dllFile.FullName); - - pluginDef = - JsonConvert.DeserializeObject( - File.ReadAllText(defJsonFile.FullName)); - } - else - { - Log.Information("Plugin DLL {0} has no definition.", dllFile.FullName); - return; - } - - var plugin = (IDalamudPlugin)Activator.CreateInstance(type); - - var dalamudInterface = new DalamudPluginInterface(this.dalamud, type.Assembly.GetName().Name); - plugin.Initialize(dalamudInterface); - Log.Information("Loaded plugin: {0}", plugin.Name); - this.Plugins.Add((plugin, pluginDef)); - } - } - } - } - - private void LoadPluginsAt(DirectoryInfo folder) { - if (folder.Exists) - { - Log.Information("Loading plugins at {0}", folder); - - var pluginDlls = folder.GetFiles("*.dll", SearchOption.AllDirectories); - - foreach (var dllFile in pluginDlls) { - LoadPluginFromAssembly(dllFile); - } - } - } - } -} diff --git a/Dalamud/Resources/eye.png b/Dalamud/Resources/eye.png deleted file mode 100644 index 5154d00df..000000000 Binary files a/Dalamud/Resources/eye.png and /dev/null differ diff --git a/Dalamud/UIRes/NotoSansCJKjp-Medium.otf b/Dalamud/UIRes/NotoSansCJKjp-Medium.otf deleted file mode 100644 index ba41937ae..000000000 Binary files a/Dalamud/UIRes/NotoSansCJKjp-Medium.otf and /dev/null differ diff --git a/Dalamud/UIRes/logo.png b/Dalamud/UIRes/logo.png deleted file mode 100644 index 34b9f0b4f..000000000 Binary files a/Dalamud/UIRes/logo.png and /dev/null differ diff --git a/Dalamud/Util.cs b/Dalamud/Util.cs deleted file mode 100644 index 8c1642c0f..000000000 --- a/Dalamud/Util.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Dalamud -{ - static class Util - { - public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16) - { - if (bytes == null) - { - return String.Empty; - } - - var hexChars = "0123456789ABCDEF".ToCharArray(); - - var offsetBlock = 8 + 3; - var byteBlock = offsetBlock + bytesPerLine * 3 + (bytesPerLine - 1) / 8 + 2; - var lineLength = byteBlock + bytesPerLine + Environment.NewLine.Length; - - var line = (new string(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray(); - var numLines = (bytes.Length + bytesPerLine - 1) / bytesPerLine; - - var sb = new StringBuilder(numLines * lineLength); - - for (var i = 0; i < bytes.Length; i += bytesPerLine) - { - var h = i + offset; - - line[0] = hexChars[(h >> 28) & 0xF]; - line[1] = hexChars[(h >> 24) & 0xF]; - line[2] = hexChars[(h >> 20) & 0xF]; - line[3] = hexChars[(h >> 16) & 0xF]; - line[4] = hexChars[(h >> 12) & 0xF]; - line[5] = hexChars[(h >> 8) & 0xF]; - line[6] = hexChars[(h >> 4) & 0xF]; - line[7] = hexChars[(h >> 0) & 0xF]; - - var hexColumn = offsetBlock; - var charColumn = byteBlock; - - for (var j = 0; j < bytesPerLine; j++) - { - if (j > 0 && (j & 7) == 0) - { - hexColumn++; - } - - if (i + j >= bytes.Length) - { - line[hexColumn] = ' '; - line[hexColumn + 1] = ' '; - line[charColumn] = ' '; - } - else - { - var by = bytes[i + j]; - line[hexColumn] = hexChars[(@by >> 4) & 0xF]; - line[hexColumn + 1] = hexChars[@by & 0xF]; - line[charColumn] = @by < 32 ? '.' : (char)@by; - } - - hexColumn += 3; - charColumn++; - } - - sb.Append(line); - } - - return sb.ToString().TrimEnd(Environment.NewLine.ToCharArray()); - } - } -} diff --git a/Dalamud/XivApi.cs b/Dalamud/XivApi.cs deleted file mode 100644 index 5f06a98fd..000000000 --- a/Dalamud/XivApi.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using Microsoft.CSharp.RuntimeBinder; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using Serilog; - -namespace Dalamud -{ - class XivApi - { - private const string URL = "https://xivapi.com/"; - - private static readonly ConcurrentDictionary cachedResponses = new ConcurrentDictionary(); - - public static async Task GetWorld(int world) - { - var res = await Get("World/" + world); - - return res; - } - - public static async Task GetClassJob(int id) - { - var res = await Get("ClassJob/" + id); - - return res; - } - - public static async Task GetFate(int id) - { - var res = await Get("Fate/" + id); - - return res; - } - - public static async Task GetCharacterSearch(string name, string world) - { - var res = await Get("character/search" + $"?name={name}&server={world}"); - - return res; - } - - public static async Task GetContentFinderCondition(int contentFinderCondition) { - return await Get("ContentFinderCondition/" + contentFinderCondition); - } - - public static async Task Search(string query, string indexes, int limit = 100, bool exact = false) { - query = System.Net.WebUtility.UrlEncode(query); - - var queryString = $"?string={query}&indexes={indexes}&limit={limit}"; - if (exact) - { - queryString += "&string_algo=match"; - } - - return await Get("search" + queryString); - } - - public static async Task GetMarketInfoWorld(int itemId, string worldName) { - return await Get($"market/{worldName}/item/{itemId}", true); - } - - public static async Task GetMarketInfoDc(int itemId, string dcName) { - return await Get($"market/item/{itemId}?dc={dcName}", true); - } - - public static async Task GetItem(int itemId) { - return await Get($"Item/{itemId}", true); - } - - public static async Task Get(string endpoint, bool noCache = false) - { - Log.Verbose("XIVAPI FETCH: {0}", endpoint); - - if (cachedResponses.TryGetValue(endpoint, out var val) && !noCache) - return val; - - var client = new HttpClient(); - var response = await client.GetAsync(URL + endpoint); - var result = await response.Content.ReadAsStringAsync(); - - var obj = JObject.Parse(result); - - if (!noCache) - cachedResponses.TryAdd(endpoint, obj); - - return obj; - } - } -} diff --git a/build.cmd b/build.cmd new file mode 100755 index 000000000..8e46664f8 --- /dev/null +++ b/build.cmd @@ -0,0 +1,6 @@ +:; set -eo pipefail +:; ./build.sh "$@" +:; exit $? + +@ECHO OFF +powershell -ExecutionPolicy ByPass -NoProfile %0\..\build.ps1 %* diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 000000000..f3f88a5db --- /dev/null +++ b/build.ps1 @@ -0,0 +1,68 @@ +[CmdletBinding()] +Param( + [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] + [string[]]$BuildArguments +) + +Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)" + +Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 } +$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent + +########################################################################### +# CONFIGURATION +########################################################################### + +$BuildProjectFile = "$PSScriptRoot\build\Build.csproj" +$TempDirectory = "$PSScriptRoot\\.tmp" + +$DotNetGlobalFile = "$PSScriptRoot\\global.json" +$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1" +$DotNetChannel = "Current" + +$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 +$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 + +########################################################################### +# EXECUTION +########################################################################### + +function ExecSafe([scriptblock] $cmd) { + & $cmd + if ($LASTEXITCODE) { exit $LASTEXITCODE } +} + +# If global.json exists, load expected version +if (Test-Path $DotNetGlobalFile) { + $DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json) + if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) { + $DotNetVersion = $DotNetGlobal.sdk.version + } +} + +# If dotnet is installed locally, and expected version is not set or installation matches the expected version +if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` + (!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) { + $env:DOTNET_EXE = (Get-Command "dotnet").Path +} +else { + $DotNetDirectory = "$TempDirectory\dotnet-win" + $env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe" + + # Download install script + $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" + New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null + (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) + + # Install by channel or version + if (!(Test-Path variable:DotNetVersion)) { + ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } + } else { + ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } + } +} + +Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" + +ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false -nologo -clp:NoSummary --verbosity quiet } +ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments } diff --git a/build.sh b/build.sh new file mode 100755 index 000000000..91dd5a44d --- /dev/null +++ b/build.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash + +echo $(bash --version 2>&1 | head -n 1) + +set -eo pipefail +SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) + +########################################################################### +# CONFIGURATION +########################################################################### + +BUILD_PROJECT_FILE="$SCRIPT_DIR/build/Build.csproj" +TEMP_DIRECTORY="$SCRIPT_DIR//.tmp" + +DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json" +DOTNET_INSTALL_URL="https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.sh" +DOTNET_CHANNEL="Current" + +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 + +########################################################################### +# EXECUTION +########################################################################### + +function FirstJsonValue { + perl -nle 'print $1 if m{"'$1'": "([^"]+)",?}' <<< ${@:2} +} + +# If global.json exists, load expected version +if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then + DOTNET_VERSION=$(FirstJsonValue "version" $(cat "$DOTNET_GLOBAL_FILE")) + if [[ "$DOTNET_VERSION" == "" ]]; then + unset DOTNET_VERSION + fi +fi + +# If dotnet is installed locally, and expected version is not set or installation matches the expected version +if [[ -x "$(command -v dotnet)" && (-z ${DOTNET_VERSION+x} || $(dotnet --version 2>&1) == "$DOTNET_VERSION") ]]; then + export DOTNET_EXE="$(command -v dotnet)" +else + DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix" + export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet" + + # Download install script + DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh" + mkdir -p "$TEMP_DIRECTORY" + curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL" + chmod +x "$DOTNET_INSTALL_FILE" + + # Install by channel or version + if [[ -z ${DOTNET_VERSION+x} ]]; then + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path + else + "$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path + fi +fi + +echo "Microsoft (R) .NET Core SDK version $("$DOTNET_EXE" --version)" + +"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false -nologo -clp:NoSummary --verbosity quiet +"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@" diff --git a/build/.editorconfig b/build/.editorconfig new file mode 100644 index 000000000..3ebe16387 --- /dev/null +++ b/build/.editorconfig @@ -0,0 +1,11 @@ +[*.cs] +dotnet_style_qualification_for_field = false:warning +dotnet_style_qualification_for_property = false:warning +dotnet_style_qualification_for_method = false:warning +dotnet_style_qualification_for_event = false:warning +dotnet_style_require_accessibility_modifiers = never:warning + +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_properties = true:warning +csharp_style_expression_bodied_indexers = true:warning +csharp_style_expression_bodied_accessors = true:warning diff --git a/build/Build.csproj b/build/Build.csproj new file mode 100644 index 000000000..73752d100 --- /dev/null +++ b/build/Build.csproj @@ -0,0 +1,16 @@ + + + + Exe + netcoreapp3.1 + CS0649;CS0169 + .. + .. + + + + + + + + diff --git a/build/Build.csproj.DotSettings b/build/Build.csproj.DotSettings new file mode 100644 index 000000000..0c57330e9 --- /dev/null +++ b/build/Build.csproj.DotSettings @@ -0,0 +1,24 @@ + + DO_NOT_SHOW + DO_NOT_SHOW + Implicit + Implicit + ExpressionBody + 0 + NEXT_LINE + True + False + 120 + IF_OWNER_IS_SINGLE_LINE + WRAP_IF_LONG + False + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /> + True + True + True + True + True + True + True + True diff --git a/build/DalamudBuild.cs b/build/DalamudBuild.cs new file mode 100644 index 000000000..4787552e4 --- /dev/null +++ b/build/DalamudBuild.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using Nuke.Common; +using Nuke.Common.Execution; +using Nuke.Common.Git; +using Nuke.Common.IO; +using Nuke.Common.ProjectModel; +using Nuke.Common.Tooling; +using Nuke.Common.Tools.DotNet; +using Nuke.Common.Tools.GitVersion; +using Nuke.Common.Utilities.Collections; +using static Nuke.Common.EnvironmentInfo; +using static Nuke.Common.IO.FileSystemTasks; +using static Nuke.Common.IO.PathConstruction; +using static Nuke.Common.Tools.DotNet.DotNetTasks; + +[CheckBuildProjectConfigurations] +[UnsetVisualStudioEnvironmentVariables] +class DalamudBuild : NukeBuild +{ + /// Support plugins are available for: + /// - JetBrains ReSharper https://nuke.build/resharper + /// - JetBrains Rider https://nuke.build/rider + /// - Microsoft VisualStudio https://nuke.build/visualstudio + /// - Microsoft VSCode https://nuke.build/vscode + + public static int Main () => Execute(x => x.Compile); + + [Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")] + readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release; + + [Solution] readonly Solution Solution; + [GitRepository] readonly GitRepository GitRepository; + [GitVersion] readonly GitVersion GitVersion; + + AbsolutePath OutputDirectory => RootDirectory / "output"; + + Target Clean => _ => _ + .Before(Restore) + .Executes(() => + { + EnsureCleanDirectory(OutputDirectory); + }); + + Target Restore => _ => _ + .Executes(() => + { + DotNetRestore(s => s + .SetProjectFile(Solution)); + }); + + Target Compile => _ => _ + .DependsOn(Restore) + .Executes(() => + { + DotNetBuild(s => s + .SetProjectFile(Solution) + .SetConfiguration(Configuration) + .SetAssemblyVersion(GitVersion.AssemblySemVer) + .SetFileVersion(GitVersion.AssemblySemFileVer) + .SetInformationalVersion(GitVersion.InformationalVersion) + /*.EnableNoRestore()*/); + }); + + Target Install => _ => _ + .DependsOn(Compile) + .Executes(() => + { + // TODO + }); +}