diff --git a/.gitmodules b/.gitmodules
index f063dd0b3..b43c5aff6 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -3,7 +3,4 @@
url = https://github.com/goatcorp/ImGuiScene
[submodule "lib/FFXIVClientStructs"]
path = lib/FFXIVClientStructs
- url = https://github.com/goatcorp/FFXIVClientStructs.git
-[submodule "lib/SharpDX.Desktop"]
- path = lib/SharpDX.Desktop
- url = https://github.com/goatcorp/SharpDX.Desktop.git
+ url = https://github.com/goatcorp/FFXIVClientStructs.git
\ No newline at end of file
diff --git a/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj b/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj
index 8c714785c..aaeee5979 100644
--- a/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj
+++ b/Dalamud.CorePlugin/Dalamud.CorePlugin.csproj
@@ -11,23 +11,22 @@
IDE0003
-
- true
- full
- false
- $(appData)\XIVLauncher\devPlugins\
+
+ $(AppData)\XIVLauncher\devPlugins\Dalamud.CorePlugin
DEBUG;TRACE
prompt
4
-
+
+ true
+ full
+ false
+
+
+
pdbonly
true
- $(appData)\XIVLauncher\devPlugins\
- TRACE
- prompt
- 4
diff --git a/Dalamud.CorePlugin/PluginImpl.cs b/Dalamud.CorePlugin/PluginImpl.cs
index 4d635eeb5..f23544cc0 100644
--- a/Dalamud.CorePlugin/PluginImpl.cs
+++ b/Dalamud.CorePlugin/PluginImpl.cs
@@ -2,6 +2,7 @@ using System;
using System.IO;
using Dalamud.Interface.Windowing;
+using Dalamud.Logging;
using Dalamud.Plugin;
namespace Dalamud.CorePlugin
diff --git a/Dalamud.CorePlugin/PluginWindow.cs b/Dalamud.CorePlugin/PluginWindow.cs
index e604389ba..9147e9d93 100644
--- a/Dalamud.CorePlugin/PluginWindow.cs
+++ b/Dalamud.CorePlugin/PluginWindow.cs
@@ -11,8 +11,6 @@ namespace Dalamud.CorePlugin
///
internal class PluginWindow : Window, IDisposable
{
- private static readonly ModuleLog Log = new("CorePlugin");
-
private readonly Dalamud dalamud;
///
@@ -20,13 +18,13 @@ namespace Dalamud.CorePlugin
///
/// The Dalamud instance.
public PluginWindow(Dalamud dalamud)
- : base("CorePlugin", ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar)
+ : base("CorePlugin")
{
this.dalamud = dalamud;
this.IsOpen = true;
this.Size = new Vector2(810, 520);
- this.SizeCondition = ImGuiCond.Always;
+ this.SizeCondition = ImGuiCond.FirstUseEver;
}
///
diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj
index eac9f1009..b2ad61f79 100644
--- a/Dalamud.Injector/Dalamud.Injector.csproj
+++ b/Dalamud.Injector/Dalamud.Injector.csproj
@@ -51,7 +51,8 @@
- IDE1006;CS1591;CS1701;CS1702
+ IDE0003;IDE0044;IDE1006;CS1591;CS1701;CS1702
+
@@ -59,9 +60,9 @@
-
+
-
+
@@ -84,6 +85,5 @@
-
diff --git a/Dalamud.Injector/EntryPoint.cs b/Dalamud.Injector/EntryPoint.cs
index eff8b81a9..5501d073c 100644
--- a/Dalamud.Injector/EntryPoint.cs
+++ b/Dalamud.Injector/EntryPoint.cs
@@ -8,7 +8,6 @@ using System.Text;
using System.Threading;
using Dalamud.Game;
-using Dalamud.Interface.Internal;
using Newtonsoft.Json;
using Reloaded.Memory.Buffers;
using Serilog;
@@ -129,13 +128,58 @@ namespace Dalamud.Injector
levelSwitch.MinimumLevel = LogEventLevel.Information;
#endif
+ CullLogFile(logPath, 1 * 1024 * 1024);
+
Log.Logger = new LoggerConfiguration()
.WriteTo.Async(a => a.File(logPath))
- .WriteTo.Sink(SerilogEventSink.Instance)
.MinimumLevel.ControlledBy(levelSwitch)
.CreateLogger();
}
+ private static void CullLogFile(string logPath, int cullingFileSize)
+ {
+ try
+ {
+ var bufferSize = 4096;
+
+ var logFile = new FileInfo(logPath);
+
+ if (!logFile.Exists)
+ logFile.Create();
+
+ if (logFile.Length <= cullingFileSize)
+ return;
+
+ var amountToCull = logFile.Length - cullingFileSize;
+
+ if (amountToCull < bufferSize)
+ return;
+
+ using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
+ using var writer = new BinaryWriter(logFile.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite));
+
+ reader.BaseStream.Seek(amountToCull, SeekOrigin.Begin);
+
+ var read = -1;
+ var total = 0;
+ var buffer = new byte[bufferSize];
+ while (read != 0)
+ {
+ read = reader.Read(buffer, 0, buffer.Length);
+ writer.Write(buffer, 0, read);
+ total += read;
+ }
+
+ writer.BaseStream.SetLength(total);
+ }
+ catch (Exception ex)
+ {
+ var caption = "XIVLauncher Error";
+ var message = $"Log cull threw an exception: {ex.Message}\n{ex.StackTrace ?? string.Empty}";
+ _ = MessageBoxW(IntPtr.Zero, message, caption, MessageBoxType.IconError | MessageBoxType.Ok);
+ }
+ }
+
private static Process GetProcess(string arg)
{
Process process;
diff --git a/Dalamud.Injector/Injector.cs b/Dalamud.Injector/Injector.cs
index 3f9c14046..20a668047 100644
--- a/Dalamud.Injector/Injector.cs
+++ b/Dalamud.Injector/Injector.cs
@@ -11,6 +11,7 @@ using PeNet.Header.Pe;
using Reloaded.Memory.Buffers;
using Reloaded.Memory.Sources;
using Reloaded.Memory.Utilities;
+using Serilog;
using static Dalamud.Injector.NativeFunctions;
using static Iced.Intel.AssemblerRegisters;
@@ -27,7 +28,7 @@ namespace Dalamud.Injector
private readonly Process targetProcess;
private readonly ExternalMemory extMemory;
private readonly CircularBuffer circularBuffer;
- private readonly PrivateMemoryBuffer privateBuffer;
+ private readonly PrivateMemoryBuffer memoryBuffer;
private IntPtr loadLibraryShellPtr;
private IntPtr loadLibraryRetPtr;
@@ -45,7 +46,7 @@ namespace Dalamud.Injector
this.extMemory = new ExternalMemory(targetProcess);
this.circularBuffer = new CircularBuffer(4096, this.extMemory);
- this.privateBuffer = new MemoryBufferHelper(targetProcess).CreatePrivateMemoryBuffer(4096);
+ this.memoryBuffer = new MemoryBufferHelper(targetProcess).CreatePrivateMemoryBuffer(4096);
using var kernel32Module = this.GetProcessModule("KERNEL32.DLL");
var kernel32PeFile = new PeFile(kernel32Module.FileName);
@@ -67,7 +68,7 @@ namespace Dalamud.Injector
this.targetProcess?.Dispose();
this.circularBuffer?.Dispose();
- this.privateBuffer?.Dispose();
+ this.memoryBuffer?.Dispose();
}
///
@@ -82,6 +83,8 @@ namespace Dalamud.Injector
if (lpParameter == IntPtr.Zero)
throw new Exception("Unable to allocate LoadLibraryW parameter");
+ Log.Verbose($"CreateRemoteThread: call 0x{this.loadLibraryShellPtr.ToInt64():X} with 0x{lpParameter.ToInt64():X}");
+
var threadHandle = CreateRemoteThread(
this.targetProcess.Handle,
IntPtr.Zero,
@@ -93,7 +96,7 @@ namespace Dalamud.Injector
_ = WaitForSingleObject(threadHandle, uint.MaxValue);
- this.extMemory.Read(this.loadLibraryRetPtr, out address);
+ address = this.extMemory.Read(this.loadLibraryRetPtr);
if (address == IntPtr.Zero)
throw new Exception($"Error calling LoadLibraryW with {modulePath}");
@@ -107,7 +110,8 @@ namespace Dalamud.Injector
/// Address to the function.
public void GetFunctionAddress(IntPtr module, string functionName, out IntPtr address)
{
- var getProcAddressParams = new GetProcAddressParams(module, this.WriteNullTerminatedASCIIString(functionName));
+ var functionNamePtr = this.WriteNullTerminatedASCIIString(functionName);
+ var getProcAddressParams = new GetProcAddressParams(module, functionNamePtr);
var lpParameter = this.circularBuffer.Add(ref getProcAddressParams);
if (lpParameter == IntPtr.Zero)
@@ -151,19 +155,25 @@ namespace Dalamud.Injector
_ = WaitForSingleObject(threadHandle, uint.MaxValue);
GetExitCodeThread(threadHandle, out exitCode);
+
+ CloseHandle(threadHandle);
}
private void SetupLoadLibrary(ProcessModule kernel32Module, ExportFunction[] kernel32Exports)
{
var offset = this.GetExportedFunctionOffset(kernel32Exports, "LoadLibraryW");
var functionAddr = kernel32Module.BaseAddress + (int)offset;
- var functionPtr = this.privateBuffer.Add(ref functionAddr);
+ Log.Verbose($"LoadLibraryW: 0x{functionAddr.ToInt64():X}");
+
+ var functionPtr = this.memoryBuffer.Add(ref functionAddr);
+ Log.Verbose($"LoadLibraryPtr: 0x{functionPtr.ToInt64():X}");
if (functionPtr == IntPtr.Zero)
throw new Exception("Unable to allocate LoadLibraryW function ptr");
- var dummy = 0L;
- this.loadLibraryRetPtr = this.privateBuffer.Add(ref dummy);
+ var dummy = IntPtr.Zero;
+ this.loadLibraryRetPtr = this.memoryBuffer.Add(ref dummy);
+ Log.Verbose($"LoadLibraryRetPtr: 0x{this.loadLibraryRetPtr.ToInt64():X}");
if (this.loadLibraryRetPtr == IntPtr.Zero)
throw new Exception("Unable to allocate LoadLibraryW return value");
@@ -180,23 +190,41 @@ namespace Dalamud.Injector
asm.ret(); // ret // Restore stack ptr. (Callee cleanup)
var bytes = this.Assemble(asm);
- this.loadLibraryShellPtr = this.privateBuffer.Add(bytes);
+ this.loadLibraryShellPtr = this.memoryBuffer.Add(bytes);
+ Log.Verbose($"LoadLibraryShellPtr: 0x{this.loadLibraryShellPtr.ToInt64():X}");
if (this.loadLibraryShellPtr == IntPtr.Zero)
throw new Exception("Unable to allocate LoadLibraryW shellcode");
+
+ this.extMemory.ChangePermission(this.loadLibraryShellPtr, bytes.Length, Reloaded.Memory.Kernel32.Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE);
+
+#if DEBUG
+ var outFunctionPtr = this.extMemory.Read(functionPtr);
+ Log.Verbose($"LoadLibraryPtr: {this.GetResultMarker(outFunctionPtr == functionAddr)}");
+
+ var outRetPtr = this.extMemory.Read(this.loadLibraryRetPtr);
+ Log.Verbose($"LoadLibraryRet: {this.GetResultMarker(dummy == outRetPtr)}");
+
+ this.extMemory.ReadRaw(this.loadLibraryShellPtr, out var outBytes, bytes.Length);
+ Log.Verbose($"LoadLibraryShellPtr: {this.GetResultMarker(Enumerable.SequenceEqual(bytes, outBytes))}");
+#endif
}
private void SetupGetProcAddress(ProcessModule kernel32Module, ExportFunction[] kernel32Exports)
{
var offset = this.GetExportedFunctionOffset(kernel32Exports, "GetProcAddress");
var functionAddr = kernel32Module.BaseAddress + (int)offset;
- var functionPtr = this.privateBuffer.Add(ref functionAddr);
+ Log.Verbose($"GetProcAddress: 0x{functionAddr.ToInt64():X}");
+
+ var functionPtr = this.memoryBuffer.Add(ref functionAddr);
+ Log.Verbose($"GetProcAddressPtr: 0x{functionPtr.ToInt64():X}");
if (functionPtr == IntPtr.Zero)
throw new Exception("Unable to allocate GetProcAddress function ptr");
- var dummy = 0L;
- this.getProcAddressRetPtr = this.privateBuffer.Add(ref dummy);
+ var dummy = IntPtr.Zero;
+ this.getProcAddressRetPtr = this.memoryBuffer.Add(ref dummy);
+ Log.Verbose($"GetProcAddressRetPtr: 0x{this.loadLibraryRetPtr.ToInt64():X}");
if (this.getProcAddressRetPtr == IntPtr.Zero)
throw new Exception("Unable to allocate GetProcAddress return value");
@@ -215,10 +243,24 @@ namespace Dalamud.Injector
asm.ret(); // ret // Restore stack ptr. (Callee cleanup)
var bytes = this.Assemble(asm);
- this.getProcAddressShellPtr = this.privateBuffer.Add(bytes);
+ this.getProcAddressShellPtr = this.memoryBuffer.Add(bytes);
+ Log.Verbose($"GetProcAddressShellPtr: 0x{this.getProcAddressShellPtr.ToInt64():X}");
if (this.getProcAddressShellPtr == IntPtr.Zero)
throw new Exception("Unable to allocate GetProcAddress shellcode");
+
+ this.extMemory.ChangePermission(this.getProcAddressShellPtr, bytes.Length, Reloaded.Memory.Kernel32.Kernel32.MEM_PROTECTION.PAGE_EXECUTE_READWRITE);
+
+#if DEBUG
+ var outFunctionPtr = this.extMemory.Read(functionPtr);
+ Log.Verbose($"GetProcAddressPtr: {this.GetResultMarker(outFunctionPtr == functionAddr)}");
+
+ var outRetPtr = this.extMemory.Read(this.loadLibraryRetPtr);
+ Log.Verbose($"GetProcAddressRet: {this.GetResultMarker(dummy == outRetPtr)}");
+
+ this.extMemory.ReadRaw(this.getProcAddressShellPtr, out var outBytes, bytes.Length);
+ Log.Verbose($"GetProcAddressShellPtr: {this.GetResultMarker(Enumerable.SequenceEqual(bytes, outBytes))}");
+#endif
}
private byte[] Assemble(Assembler assembler)
@@ -264,28 +306,42 @@ namespace Dalamud.Injector
return exportFunction.Address;
}
- private IntPtr WriteNullTerminatedASCIIString(string libraryPath)
+ private IntPtr WriteNullTerminatedASCIIString(string value)
{
- var libraryNameBytes = Encoding.ASCII.GetBytes(libraryPath + '\0');
- var value = this.circularBuffer.Add(libraryNameBytes);
+ var bytes = Encoding.ASCII.GetBytes(value + '\0');
+ var address = this.circularBuffer.Add(bytes);
- if (value == IntPtr.Zero)
+ if (address == IntPtr.Zero)
throw new Exception("Unable to write ASCII string to buffer");
- return value;
+#if DEBUG
+ this.extMemory.ReadRaw(address, out var outBytes, bytes.Length);
+ Log.Verbose($"WriteASCII: {this.GetResultMarker(Enumerable.SequenceEqual(bytes, outBytes))} 0x{address.ToInt64():X} {value}");
+#endif
+
+ return address;
}
- private IntPtr WriteNullTerminatedUnicodeString(string libraryPath)
+ private IntPtr WriteNullTerminatedUnicodeString(string value)
{
- var libraryNameBytes = Encoding.Unicode.GetBytes(libraryPath + '\0');
- var value = this.circularBuffer.Add(libraryNameBytes);
+ var bytes = Encoding.Unicode.GetBytes(value + '\0');
+ var address = this.circularBuffer.Add(bytes);
- if (value == IntPtr.Zero)
+ if (address == IntPtr.Zero)
throw new Exception("Unable to write Unicode string to buffer");
- return value;
+#if DEBUG
+ this.extMemory.ReadRaw(address, out var outBytes, bytes.Length);
+ Log.Verbose($"WriteUnicode: {this.GetResultMarker(Enumerable.SequenceEqual(bytes, outBytes))} 0x{address.ToInt64():X} {value}");
+#endif
+
+ return address;
}
+#if DEBUG
+ private string GetResultMarker(bool result) => result ? "✅" : "❌";
+#endif
+
[StructLayout(LayoutKind.Sequential)]
private struct GetProcAddressParams
{
diff --git a/Dalamud.Injector/NativeFunctions.cs b/Dalamud.Injector/NativeFunctions.cs
index 46da6728c..b9ed9f33d 100644
--- a/Dalamud.Injector/NativeFunctions.cs
+++ b/Dalamud.Injector/NativeFunctions.cs
@@ -582,6 +582,22 @@ namespace Dalamud.Injector
WAIT_FAILED = 0xFFFFFFF,
}
+ ///
+ /// Closes an open object handle.
+ ///
+ ///
+ /// A valid handle to an open object.
+ ///
+ ///
+ /// If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error
+ /// information, call GetLastError. If the application is running under a debugger, the function will throw an exception if it receives
+ /// either a handle value that is not valid or a pseudo-handle value. This can happen if you close a handle twice, or if you call
+ /// CloseHandle on a handle returned by the FindFirstFile function instead of calling the FindClose function.
+ ///
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern bool CloseHandle(IntPtr hObject);
+
///
/// Creates a thread that runs in the virtual address space of another process. Use the CreateRemoteThreadEx function
/// to create a thread that runs in the virtual address space of another process and optionally specify extended attributes.
@@ -651,6 +667,34 @@ namespace Dalamud.Injector
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);
+ ///
+ /// Opens an existing local process object.
+ ///
+ ///
+ /// The access to the process object. This access right is checked against the security descriptor for the process. This parameter can be one or
+ /// more of the process access rights. If the caller has enabled the SeDebugPrivilege privilege, the requested access is granted regardless of the
+ /// contents of the security descriptor.
+ ///
+ ///
+ /// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
+ ///
+ ///
+ /// The identifier of the local process to be opened. If the specified process is the System Idle Process(0x00000000), the function fails and the
+ /// last error code is ERROR_INVALID_PARAMETER.If the specified process is the System process or one of the Client Server Run-Time Subsystem(CSRSS)
+ /// processes, this function fails and the last error code is ERROR_ACCESS_DENIED because their access restrictions prevent user-level code from
+ /// opening them. If you are using GetCurrentProcessId as an argument to this function, consider using GetCurrentProcess instead of OpenProcess, for
+ /// improved performance.
+ ///
+ ///
+ /// If the function succeeds, the return value is an open handle to the specified process.
+ /// If the function fails, the return value is NULL.To get extended error information, call GetLastError.
+ ///
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr OpenProcess(
+ ProcessAccessFlags dwDesiredAccess,
+ bool bInheritHandle,
+ int dwProcessId);
+
///
/// See https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex.
/// Reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process.
diff --git a/Dalamud.Injector/RemotePinnedData.cs b/Dalamud.Injector/RemotePinnedData.cs
deleted file mode 100644
index fc713639f..000000000
--- a/Dalamud.Injector/RemotePinnedData.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.Runtime.InteropServices;
-using System.Text;
-
-using static Dalamud.Injector.NativeFunctions;
-
-namespace Dalamud.Injector
-{
- ///
- /// Pin an arbitrary string to a remote process.
- ///
- internal class RemotePinnedData : IDisposable
- {
- private readonly Process process;
- private readonly byte[] data;
- private readonly IntPtr allocAddr;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Process to write in.
- /// Data to write.
- public unsafe RemotePinnedData(Process process, byte[] data)
- {
- this.process = process;
- this.data = data;
-
- this.allocAddr = VirtualAllocEx(
- this.process.Handle,
- IntPtr.Zero,
- this.data.Length,
- AllocationType.Commit,
- MemoryProtection.ReadWrite);
-
- if (this.allocAddr == IntPtr.Zero || Marshal.GetLastWin32Error() != 0)
- {
- throw new Exception("Error allocating memory");
- }
-
- var result = WriteProcessMemory(
- this.process.Handle,
- this.allocAddr,
- this.data,
- this.data.Length,
- out _);
-
- if (!result || Marshal.GetLastWin32Error() != 0)
- {
- throw new Exception("Error writing memory");
- }
- }
-
- ///
- /// Gets the address of the pinned data.
- ///
- public IntPtr Address => this.allocAddr;
-
- ///
- public void Dispose()
- {
- if (this.allocAddr == IntPtr.Zero)
- {
- return;
- }
-
- var result = VirtualFreeEx(
- this.process.Handle,
- this.allocAddr,
- 0,
- AllocationType.Release);
-
- if (!result || Marshal.GetLastWin32Error() != 0)
- {
- throw new Exception("Error freeing memory");
- }
- }
- }
-}
diff --git a/Dalamud/Configuration/Internal/DalamudConfiguration.cs b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
index ed10572e4..4eb6e3b03 100644
--- a/Dalamud/Configuration/Internal/DalamudConfiguration.cs
+++ b/Dalamud/Configuration/Internal/DalamudConfiguration.cs
@@ -47,12 +47,12 @@ namespace Dalamud.Configuration.Internal
///
/// Gets or sets the language code to load Dalamud localization with.
///
- public string LanguageOverride { get; set; }
+ public string LanguageOverride { get; set; } = null;
///
/// Gets or sets the last loaded Dalamud version.
///
- public string LastVersion { get; set; }
+ public string LastVersion { get; set; } = null;
///
/// Gets or sets the chat type used by default for plugin messages.
@@ -62,17 +62,17 @@ namespace Dalamud.Configuration.Internal
///
/// Gets or sets a value indicating whether or not plugin testing builds should be shown.
///
- public bool DoPluginTest { get; set; }
+ public bool DoPluginTest { get; set; } = false;
///
/// Gets or sets a value indicating whether or not Dalamud testing builds should be used.
///
- public bool DoDalamudTest { get; set; }
+ public bool DoDalamudTest { get; set; } = false;
///
/// Gets or sets a value indicating whether or not XL should download the Dalamud .NET runtime.
///
- public bool DoDalamudRuntime { get; set; }
+ public bool DoDalamudRuntime { get; set; } = false;
///
/// Gets or sets a list of custom repos.
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index 2de2bcb7c..85d8d9c86 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -59,9 +59,9 @@
-
-
-
+
+
+
diff --git a/Dalamud/EntryPoint.cs b/Dalamud/EntryPoint.cs
index 7cfe03443..378f841fd 100644
--- a/Dalamud/EntryPoint.cs
+++ b/Dalamud/EntryPoint.cs
@@ -6,12 +6,14 @@ using System.Threading;
using System.Threading.Tasks;
using Dalamud.Configuration.Internal;
-using Dalamud.Interface.Internal;
+using Dalamud.Logging.Internal;
using Newtonsoft.Json;
using Serilog;
using Serilog.Core;
using Serilog.Events;
+using static Dalamud.NativeFunctions;
+
namespace Dalamud
{
///
@@ -43,11 +45,16 @@ namespace Dalamud
/// The containing information needed to initialize Dalamud.
private static void RunThread(DalamudStartInfo info)
{
+ // Setup logger
+ var levelSwitch = InitLogging(info.WorkingDirectory);
+
// Load configuration first to get some early persistent state, like log level
var configuration = DalamudConfiguration.Load(info.ConfigurationPath);
- // Setup logger
- var levelSwitch = InitLogging(info.WorkingDirectory, configuration);
+ // Set the appropriate logging level from the configuration
+#if !DEBUG
+ levelSwitch.MinimumLevel = configuration.LogLevel;
+#endif
// Log any unhandled exception.
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
@@ -88,30 +95,96 @@ namespace Dalamud
}
}
- private static LoggingLevelSwitch InitLogging(string baseDirectory, DalamudConfiguration configuration)
+ private static LoggingLevelSwitch InitLogging(string baseDirectory)
{
#if DEBUG
var logPath = Path.Combine(baseDirectory, "dalamud.log");
+ var oldPath = Path.Combine(baseDirectory, "dalamud.log.old");
#else
var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log");
+ var oldPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log.old");
#endif
- var levelSwitch = new LoggingLevelSwitch();
+ CullLogFile(logPath, oldPath, 1 * 1024 * 1024);
+ CullLogFile(oldPath, null, 10 * 1024 * 1024);
-#if DEBUG
- levelSwitch.MinimumLevel = LogEventLevel.Verbose;
-#else
- levelSwitch.MinimumLevel = configuration.LogLevel;
-#endif
+ var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
Log.Logger = new LoggerConfiguration()
- .WriteTo.Async(a => a.File(logPath, fileSizeLimitBytes: 5 * 1024 * 1024, rollOnFileSizeLimit: true))
- .WriteTo.Sink(SerilogEventSink.Instance)
- .MinimumLevel.ControlledBy(levelSwitch)
- .CreateLogger();
+ .WriteTo.Async(a => a.File(logPath))
+ .WriteTo.Sink(SerilogEventSink.Instance)
+ .MinimumLevel.ControlledBy(levelSwitch)
+ .CreateLogger();
return levelSwitch;
}
+ private static void CullLogFile(string logPath, string? oldPath, int cullingFileSize)
+ {
+ try
+ {
+ var bufferSize = 4096;
+
+ var logFile = new FileInfo(logPath);
+
+ if (!logFile.Exists)
+ logFile.Create();
+
+ if (logFile.Length <= cullingFileSize)
+ return;
+
+ var amountToCull = logFile.Length - cullingFileSize;
+
+ if (amountToCull < bufferSize)
+ return;
+
+ if (oldPath != null)
+ {
+ var oldFile = new FileInfo(oldPath);
+
+ if (!oldFile.Exists)
+ oldFile.Create();
+
+ using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read));
+ using var writer = new BinaryWriter(oldFile.Open(FileMode.Append, FileAccess.Write));
+
+ var read = -1;
+ var total = 0;
+ var buffer = new byte[bufferSize];
+ while (read != 0 && total < amountToCull)
+ {
+ read = reader.Read(buffer, 0, buffer.Length);
+ writer.Write(buffer, 0, read);
+ total += read;
+ }
+ }
+
+ {
+ using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite));
+ using var writer = new BinaryWriter(logFile.Open(FileMode.Open, FileAccess.Write, FileShare.ReadWrite));
+
+ reader.BaseStream.Seek(amountToCull, SeekOrigin.Begin);
+
+ var read = -1;
+ var total = 0;
+ var buffer = new byte[bufferSize];
+ while (read != 0)
+ {
+ read = reader.Read(buffer, 0, buffer.Length);
+ writer.Write(buffer, 0, read);
+ total += read;
+ }
+
+ writer.BaseStream.SetLength(total);
+ }
+ }
+ catch (Exception ex)
+ {
+ var caption = "XIVLauncher Error";
+ var message = $"Log cull threw an exception: {ex.Message}\n{ex.StackTrace ?? string.Empty}";
+ _ = MessageBoxW(IntPtr.Zero, message, caption, MessageBoxType.IconError | MessageBoxType.Ok);
+ }
+ }
+
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
{
switch (args.ExceptionObject)
diff --git a/Dalamud/Game/Internal/Network/GameNetwork.cs b/Dalamud/Game/Internal/Network/GameNetwork.cs
index 947a4651c..dff3ac535 100644
--- a/Dalamud/Game/Internal/Network/GameNetwork.cs
+++ b/Dalamud/Game/Internal/Network/GameNetwork.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
+using Dalamud.Game.Network;
using Dalamud.Hooking;
using Serilog;
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/IMarketBoardUploader.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs
similarity index 93%
rename from Dalamud/Game/Network/MarketBoardUploaders/IMarketBoardUploader.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs
index 9820ac237..a867261f2 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/IMarketBoardUploader.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs
@@ -1,6 +1,6 @@
using Dalamud.Game.Network.Structures;
-namespace Dalamud.Game.Network.MarketBoardUploaders
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders
{
///
/// An interface binding for the Universalis uploader.
diff --git a/Dalamud/Game/Network/Internal/MarketBoardUploaders/MarketBoardItemRequest.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/MarketBoardItemRequest.cs
new file mode 100644
index 000000000..63d51f0e1
--- /dev/null
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/MarketBoardItemRequest.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+
+using Dalamud.Game.Network.Structures;
+
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders
+{
+ ///
+ /// This represents a submission to a marketboard aggregation website.
+ ///
+ internal class MarketBoardItemRequest
+ {
+ ///
+ /// Gets or sets the catalog ID.
+ ///
+ public uint CatalogId { get; set; }
+
+ ///
+ /// Gets or sets the amount to arrive.
+ ///
+ public byte AmountToArrive { get; set; }
+
+ ///
+ /// Gets or sets the offered item listings.
+ ///
+ public List Listings { get; set; }
+
+ ///
+ /// Gets or sets the historical item listings.
+ ///
+ public List History { get; set; }
+
+ ///
+ /// Gets or sets the listing request ID.
+ ///
+ public int ListingsRequestId { get; set; } = -1;
+
+ ///
+ /// Gets a value indicating whether the upload is complete.
+ ///
+ public bool IsDone => this.Listings.Count == this.AmountToArrive && this.History.Count != 0;
+ }
+}
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryEntry.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisHistoryEntry.cs
similarity index 95%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryEntry.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisHistoryEntry.cs
index ba60d484d..37467377c 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryEntry.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisHistoryEntry.cs
@@ -1,6 +1,6 @@
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryUploadRequest.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisHistoryUploadRequest.cs
similarity index 91%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryUploadRequest.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisHistoryUploadRequest.cs
index 1c92171af..afa8bf417 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisHistoryUploadRequest.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisHistoryUploadRequest.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingDeleteRequest.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingDeleteRequest.cs
similarity index 88%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingDeleteRequest.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingDeleteRequest.cs
index f6994e60f..ea96f934a 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingDeleteRequest.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingDeleteRequest.cs
@@ -1,11 +1,11 @@
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// Request payload for market board purchases.
///
- public class UniversalisItemListingDeleteRequest
+ internal class UniversalisItemListingDeleteRequest
{
///
/// Gets or sets the object ID of the retainer associated with the sale.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsEntry.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingsEntry.cs
similarity index 97%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsEntry.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingsEntry.cs
index 745c2a66e..42ff15668 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsEntry.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingsEntry.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsUploadRequest.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingsUploadRequest.cs
similarity index 91%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsUploadRequest.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingsUploadRequest.cs
index 3623769c9..c055b30d9 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemListingsUploadRequest.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemListingsUploadRequest.cs
@@ -2,7 +2,7 @@ using System.Collections.Generic;
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemMateria.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemMateria.cs
similarity index 85%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemMateria.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemMateria.cs
index 5c2cae7c6..8c9c99bb5 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisItemMateria.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisItemMateria.cs
@@ -1,6 +1,6 @@
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxData.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisTaxData.cs
similarity index 93%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxData.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisTaxData.cs
index dd56a25ed..0a93f788b 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxData.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisTaxData.cs
@@ -1,6 +1,6 @@
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxUploadRequest.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisTaxUploadRequest.cs
similarity index 90%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxUploadRequest.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisTaxUploadRequest.cs
index bdf9715a0..a11ac0e89 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisTaxUploadRequest.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/Types/UniversalisTaxUploadRequest.cs
@@ -1,6 +1,6 @@
using Newtonsoft.Json;
-namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
{
///
/// A Universalis API structure.
diff --git a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs
similarity index 62%
rename from Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs
rename to Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs
index 58c7810ad..5e4ac76e1 100644
--- a/Dalamud/Game/Network/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs
+++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs
@@ -1,14 +1,15 @@
using System;
using System.Collections.Generic;
-using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
-using Dalamud.Game.Network.MarketBoardUploaders;
-using Dalamud.Game.Network.MarketBoardUploaders.Universalis;
+using Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types;
using Dalamud.Game.Network.Structures;
using Newtonsoft.Json;
using Serilog;
-namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
+namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis
{
///
/// This class represents an uploader for contributing data to Universalis.
@@ -16,8 +17,8 @@ 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;
@@ -34,14 +35,14 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
///
public void Upload(MarketBoardItemRequest request)
{
- using var client = new WebClient();
-
- client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
+ using var client = new HttpClient();
Log.Verbose("Starting Universalis upload.");
var uploader = this.dalamud.ClientState.LocalContentId;
- var listingsRequestObject = new UniversalisItemListingsUploadRequest
+ // ====================================================================================
+
+ var listingsUploadObject = new UniversalisItemListingsUploadRequest
{
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
UploaderId = uploader.ToString(),
@@ -76,14 +77,17 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
});
}
- listingsRequestObject.Listings.Add(universalisListing);
+ listingsUploadObject.Listings.Add(universalisListing);
}
- var upload = JsonConvert.SerializeObject(listingsRequestObject);
- Log.Verbose(upload);
- client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", upload);
+ var listingPath = "/upload";
+ var listingUpload = JsonConvert.SerializeObject(listingsUploadObject);
+ Log.Verbose($"{listingPath}: {listingUpload}");
+ client.PostAsync($"{ApiBase}{listingPath}/{ApiKey}", new StringContent(listingUpload, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
- var historyRequestObject = new UniversalisHistoryUploadRequest
+ // ====================================================================================
+
+ var historyUploadObject = new UniversalisHistoryUploadRequest
{
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
UploaderId = uploader.ToString(),
@@ -93,7 +97,7 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
foreach (var marketBoardHistoryListing in request.History)
{
- historyRequestObject.Entries.Add(new UniversalisHistoryEntry
+ historyUploadObject.Entries.Add(new UniversalisHistoryEntry
{
BuyerName = marketBoardHistoryListing.BuyerName,
Hq = marketBoardHistoryListing.IsHq,
@@ -104,11 +108,12 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
});
}
- client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
+ var historyPath = "/upload";
+ var historyUpload = JsonConvert.SerializeObject(historyUploadObject);
+ Log.Verbose($"{historyPath}: {historyUpload}");
+ client.PostAsync($"{ApiBase}{historyPath}/{ApiKey}", new StringContent(historyUpload, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
- var historyUpload = JsonConvert.SerializeObject(historyRequestObject);
- Log.Verbose(historyUpload);
- client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
+ // ====================================================================================
Log.Verbose("Universalis data upload for item#{0} completed.", request.CatalogId);
}
@@ -116,9 +121,11 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
///
public void UploadTax(MarketTaxRates taxRates)
{
- using var client = new WebClient();
+ using var client = new HttpClient();
- var taxRatesRequest = new UniversalisTaxUploadRequest
+ // ====================================================================================
+
+ var taxUploadObject = new UniversalisTaxUploadRequest
{
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
UploaderId = this.dalamud.ClientState.LocalContentId.ToString(),
@@ -133,26 +140,35 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
},
};
- client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
+ var taxPath = "/upload";
+ var taxUpload = JsonConvert.SerializeObject(taxUploadObject);
+ Log.Verbose($"{taxPath}: {taxUpload}");
- var historyUpload = JsonConvert.SerializeObject(taxRatesRequest);
- Log.Verbose(historyUpload);
- client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
+ client.PostAsync($"{ApiBase}{taxPath}/{ApiKey}", new StringContent(taxUpload, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
+
+ // ====================================================================================
Log.Verbose("Universalis tax upload completed.");
}
///
+ ///
+ /// It may seem backwards that an upload only performs a delete request, however this is not trying
+ /// to track the available listings, that is done via the listings packet. All this does is remove
+ /// a listing, or delete it, when a purchase has been made.
+ ///
public void UploadPurchase(MarketBoardPurchaseHandler purchaseHandler)
{
- using var client = new WebClient();
- client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
- client.Headers.Add(HttpRequestHeader.Authorization, ApiKey);
+ using var client = new HttpClient();
+
+ client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(ApiKey);
var itemId = purchaseHandler.CatalogId;
var worldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
- var purchaseRequest = new UniversalisItemListingDeleteRequest
+ // ====================================================================================
+
+ var deleteListingObject = new UniversalisItemListingDeleteRequest
{
PricePerUnit = purchaseHandler.PricePerUnit,
Quantity = purchaseHandler.ItemQuantity,
@@ -161,11 +177,13 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
UploaderId = this.dalamud.ClientState.LocalContentId.ToString(),
};
- var requestPath = ApiBase + $"/api/{worldId}/{itemId}/delete";
- var purchaseUpload = JsonConvert.SerializeObject(purchaseRequest);
- Log.Verbose($"Making request to {requestPath}");
- Log.Verbose(purchaseUpload);
- client.UploadString(requestPath, "POST", purchaseUpload);
+ var deletePath = $"/api/{worldId}/{itemId}/delete";
+ var deleteListing = JsonConvert.SerializeObject(deleteListingObject);
+ Log.Verbose($"{deletePath}: {deleteListing}");
+
+ client.PostAsync($"{ApiBase}{deletePath}", new StringContent(deleteListing, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
+
+ // ====================================================================================
Log.Verbose("Universalis purchase upload completed.");
}
diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/Internal/NetworkHandlers.cs
similarity index 92%
rename from Dalamud/Game/Network/NetworkHandlers.cs
rename to Dalamud/Game/Network/Internal/NetworkHandlers.cs
index 0b7aa7694..bf20122b0 100644
--- a/Dalamud/Game/Network/NetworkHandlers.cs
+++ b/Dalamud/Game/Network/Internal/NetworkHandlers.cs
@@ -5,14 +5,13 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
-using Dalamud.Game.Internal.Network;
-using Dalamud.Game.Network.MarketBoardUploaders;
+using Dalamud.Game.Network.Internal.MarketBoardUploaders;
+using Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis;
using Dalamud.Game.Network.Structures;
-using Dalamud.Game.Network.Universalis.MarketBoardUploaders;
using Lumina.Excel.GeneratedSheets;
using Serilog;
-namespace Dalamud.Game.Network
+namespace Dalamud.Game.Network.Internal
{
///
/// This class handles network notifications and uploading market board data.
@@ -141,7 +140,7 @@ namespace Dalamud.Game.Network
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.ItemListings[0].CatalogId && !r.IsDone);
- if (request == null)
+ if (request == default)
{
Log.Error($"Market Board data arrived without a corresponding request: item#{listing.ItemListings[0].CatalogId}");
return;
@@ -207,17 +206,15 @@ namespace Dalamud.Game.Network
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);
- if (request == null)
+ if (request == default)
{
- Log.Error(
- $"Market Board data arrived without a corresponding request: item#{listing.CatalogId}");
+ 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}");
+ Log.Error($"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
return;
}
@@ -243,6 +240,7 @@ namespace Dalamud.Game.Network
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
{
var category = (uint)Marshal.ReadInt32(dataPtr);
+
// Result dialog packet does not contain market tax rates
if (category != 720905)
{
@@ -279,9 +277,9 @@ namespace Dalamud.Game.Network
// Transaction succeeded
if (purchase.ItemQuantity == this.marketBoardPurchaseHandler.ItemQuantity
&& (purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId
- || purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId + 1000000))
+ || purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId + 1_000_000))
{ // HQ
- Log.Information("Bought " + purchase.ItemQuantity + "x " + this.marketBoardPurchaseHandler.CatalogId + " for " + (this.marketBoardPurchaseHandler.PricePerUnit * purchase.ItemQuantity) + " gils, listing id is " + this.marketBoardPurchaseHandler.ListingId);
+ Log.Verbose($"Bought {purchase.ItemQuantity}x {this.marketBoardPurchaseHandler.CatalogId} for {this.marketBoardPurchaseHandler.PricePerUnit * purchase.ItemQuantity} gils, listing id is {this.marketBoardPurchaseHandler.ListingId}");
var handler = this.marketBoardPurchaseHandler; // Capture the object so that we don't pass in a null one when the task starts.
Task.Run(() => this.uploader.UploadPurchase(handler));
}
diff --git a/Dalamud/Game/Network/MarketBoardItemRequest.cs b/Dalamud/Game/Network/MarketBoardItemRequest.cs
deleted file mode 100644
index df08ce09e..000000000
--- a/Dalamud/Game/Network/MarketBoardItemRequest.cs
+++ /dev/null
@@ -1,21 +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 => this.Listings.Count == this.AmountToArrive && this.History.Count != 0;
- }
-}
diff --git a/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs b/Dalamud/Game/Network/NetworkMessageDirection.cs
similarity index 89%
rename from Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
rename to Dalamud/Game/Network/NetworkMessageDirection.cs
index 22de9cb54..79d9d2df2 100644
--- a/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
+++ b/Dalamud/Game/Network/NetworkMessageDirection.cs
@@ -1,4 +1,4 @@
-namespace Dalamud.Game.Internal.Network
+namespace Dalamud.Game.Network
{
///
/// This represents the direction of a network message.
diff --git a/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs b/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs
index 2ac0f8886..ad19f48c5 100644
--- a/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs
+++ b/Dalamud/Game/Network/Structures/MarketBoardCurrentOfferings.cs
@@ -5,14 +5,43 @@ using System.Text;
namespace Dalamud.Game.Network.Structures
{
+ ///
+ /// This class represents the current market board offerings from a game network packet.
+ ///
public class MarketBoardCurrentOfferings
{
- public List ItemListings;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal MarketBoardCurrentOfferings()
+ {
+ }
- public int ListingIndexEnd;
- public int ListingIndexStart;
- public int RequestId;
+ ///
+ /// Gets the list of individual item listings.
+ ///
+ public List ItemListings { get; internal set; }
+ ///
+ /// Gets the listing end index.
+ ///
+ public int ListingIndexEnd { get; internal set; }
+
+ ///
+ /// Gets the listing start index.
+ ///
+ public int ListingIndexStart { get; internal set; }
+
+ ///
+ /// Gets the request ID.
+ ///
+ public int RequestId { get; internal set; }
+
+ ///
+ /// Read a object from memory.
+ ///
+ /// Address to read.
+ /// A new object.
public static unsafe MarketBoardCurrentOfferings Read(IntPtr dataPtr)
{
var output = new MarketBoardCurrentOfferings();
@@ -80,32 +109,124 @@ namespace Dalamud.Game.Network.Structures
return output;
}
+ ///
+ /// This class represents the current market board offering of a single item from the network packet.
+ ///
public class MarketBoardItemListing
{
- public ulong ArtisanId;
- public uint CatalogId;
- public bool IsHq;
- public uint ItemQuantity;
- public DateTime LastReviewTime;
- public ulong ListingId;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal MarketBoardItemListing()
+ {
+ }
- public List Materia;
- public int MateriaCount;
- public bool OnMannequin;
- public string PlayerName;
- public uint PricePerUnit;
- public int RetainerCityId;
- public ulong RetainerId;
+ ///
+ /// Gets the artisan ID.
+ ///
+ public ulong ArtisanId { get; internal set; }
- public string RetainerName;
- public ulong RetainerOwnerId;
- public int StainId;
- public uint TotalTax;
+ ///
+ /// Gets the catalog ID.
+ ///
+ public uint CatalogId { get; internal set; }
+ ///
+ /// Gets a value indicating whether the item is HQ.
+ ///
+ public bool IsHq { get; internal set; }
+
+ ///
+ /// Gets the item quantity.
+ ///
+ public uint ItemQuantity { get; internal set; }
+
+ ///
+ /// Gets the time this offering was last reviewed.
+ ///
+ public DateTime LastReviewTime { get; internal set; }
+
+ ///
+ /// Gets the listing ID.
+ ///
+ public ulong ListingId { get; internal set; }
+
+ ///
+ /// Gets the list of materia attached to this item.
+ ///
+ public List Materia { get; internal set; }
+
+ ///
+ /// Gets the amount of attached materia.
+ ///
+ public int MateriaCount { get; internal set; }
+
+ ///
+ /// Gets a value indicating whether this item is on a mannequin.
+ ///
+ public bool OnMannequin { get; internal set; }
+
+ ///
+ /// Gets the player name.
+ ///
+ public string PlayerName { get; internal set; }
+
+ ///
+ /// Gets the price per unit.
+ ///
+ public uint PricePerUnit { get; internal set; }
+
+ ///
+ /// Gets the city ID of the retainer selling the item.
+ ///
+ public int RetainerCityId { get; internal set; }
+
+ ///
+ /// Gets the ID of the retainer selling the item.
+ ///
+ public ulong RetainerId { get; internal set; }
+
+ ///
+ /// Gets the name of the retainer.
+ ///
+ public string RetainerName { get; internal set; }
+
+ ///
+ /// Gets the ID of the retainer's owner.
+ ///
+ public ulong RetainerOwnerId { get; internal set; }
+
+ ///
+ /// Gets the stain or applied dye of the item.
+ ///
+ public int StainId { get; internal set; }
+
+ ///
+ /// Gets the total tax.
+ ///
+ public uint TotalTax { get; internal set; }
+
+ ///
+ /// This represents the materia slotted to an .
+ ///
public class ItemMateria
{
- public int Index;
- public int MateriaId;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal ItemMateria()
+ {
+ }
+
+ ///
+ /// Gets the materia index.
+ ///
+ public int Index { get; internal set; }
+
+ ///
+ /// Gets the materia ID.
+ ///
+ public int MateriaId { get; internal set; }
}
}
}
diff --git a/Dalamud/Game/Network/Structures/MarketBoardHistory.cs b/Dalamud/Game/Network/Structures/MarketBoardHistory.cs
index b2f3e3ad0..c73529da3 100644
--- a/Dalamud/Game/Network/Structures/MarketBoardHistory.cs
+++ b/Dalamud/Game/Network/Structures/MarketBoardHistory.cs
@@ -5,13 +5,38 @@ using System.Text;
namespace Dalamud.Game.Network.Structures
{
+ ///
+ /// This class represents the market board history from a game network packet.
+ ///
public class MarketBoardHistory
{
- public uint CatalogId;
- public uint CatalogId2;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal MarketBoardHistory()
+ {
+ }
- public List HistoryListings;
+ ///
+ /// Gets the catalog ID.
+ ///
+ public uint CatalogId { get; internal set; }
+ ///
+ /// Gets the second catalog ID.
+ ///
+ public uint CatalogId2 { get; internal set; }
+
+ ///
+ /// Gets the list of individual item history listings.
+ ///
+ public List HistoryListings { get; internal set; }
+
+ ///
+ /// Read a object from memory.
+ ///
+ /// Address to read.
+ /// A new object.
public static unsafe MarketBoardHistory Read(IntPtr dataPtr)
{
var output = new MarketBoardHistory();
@@ -47,16 +72,52 @@ namespace Dalamud.Game.Network.Structures
return output;
}
+ ///
+ /// This class represents the market board history of a single item from the network packet.
+ ///
public class MarketBoardHistoryListing
{
- public string BuyerName;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal MarketBoardHistoryListing()
+ {
+ }
- public uint CatalogId;
- public bool IsHq;
- public bool OnMannequin;
- public DateTime PurchaseTime;
- public uint Quantity;
- public uint SalePrice;
+ ///
+ /// Gets the buyer's name.
+ ///
+ public string BuyerName { get; internal set; }
+
+ ///
+ /// Gets the catalog ID.
+ ///
+ public uint CatalogId { get; internal set; }
+
+ ///
+ /// Gets a value indicating whether the item is HQ.
+ ///
+ public bool IsHq { get; internal set; }
+
+ ///
+ /// Gets a value indicating whether the item is on a mannequin.
+ ///
+ public bool OnMannequin { get; internal set; }
+
+ ///
+ /// Gets the time of purchase.
+ ///
+ public DateTime PurchaseTime { get; internal set; }
+
+ ///
+ /// Gets the quantity.
+ ///
+ public uint Quantity { get; internal set; }
+
+ ///
+ /// Gets the sale price.
+ ///
+ public uint SalePrice { get; internal set; }
}
}
}
diff --git a/Dalamud/Game/Network/Structures/MarketTaxRates.cs b/Dalamud/Game/Network/Structures/MarketTaxRates.cs
index 4a79c0242..5b27b9415 100644
--- a/Dalamud/Game/Network/Structures/MarketTaxRates.cs
+++ b/Dalamud/Game/Network/Structures/MarketTaxRates.cs
@@ -3,15 +3,53 @@ using System.IO;
namespace Dalamud.Game.Network.Structures
{
+ ///
+ /// This class represents the market tax rates from a game network packet.
+ ///
public class MarketTaxRates
{
- public uint LimsaLominsaTax;
- public uint GridaniaTax;
- public uint UldahTax;
- public uint IshgardTax;
- public uint KuganeTax;
- public uint CrystariumTax;
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal MarketTaxRates()
+ {
+ }
+ ///
+ /// Gets the tax rate in Limsa Lominsa.
+ ///
+ public uint LimsaLominsaTax { get; internal set; }
+
+ ///
+ /// Gets the tax rate in Gridania.
+ ///
+ public uint GridaniaTax { get; internal set; }
+
+ ///
+ /// Gets the tax rate in Ul'dah.
+ ///
+ public uint UldahTax { get; internal set; }
+
+ ///
+ /// Gets the tax rate in Ishgard.
+ ///
+ public uint IshgardTax { get; internal set; }
+
+ ///
+ /// Gets the tax rate in Kugane.
+ ///
+ public uint KuganeTax { get; internal set; }
+
+ ///
+ /// Gets the tax rate in the Crystarium.
+ ///
+ public uint CrystariumTax { get; internal set; }
+
+ ///
+ /// Read a object from memory.
+ ///
+ /// Address to read.
+ /// A new object.
public static unsafe MarketTaxRates Read(IntPtr dataPtr)
{
var output = new MarketTaxRates();
diff --git a/Dalamud/Hooking/Internal/HookManager.cs b/Dalamud/Hooking/Internal/HookManager.cs
index 5741b7d29..ecf03f1af 100644
--- a/Dalamud/Hooking/Internal/HookManager.cs
+++ b/Dalamud/Hooking/Internal/HookManager.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
+using Dalamud.Logging.Internal;
using Dalamud.Memory;
using Microsoft.Win32;
diff --git a/Dalamud/Interface/Internal/DalamudInterface.cs b/Dalamud/Interface/Internal/DalamudInterface.cs
index 47225e815..630f01296 100644
--- a/Dalamud/Interface/Internal/DalamudInterface.cs
+++ b/Dalamud/Interface/Internal/DalamudInterface.cs
@@ -6,7 +6,8 @@ using System.Runtime.InteropServices;
using Dalamud.Interface.Internal.Windows;
using Dalamud.Interface.Windowing;
-using Dalamud.Plugin;
+using Dalamud.Logging;
+using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal;
using ImGuiNET;
using Serilog.Events;
diff --git a/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs b/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs
index ad20b493e..4fdbd64f5 100644
--- a/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs
+++ b/Dalamud/Interface/Internal/Scratchpad/ScratchMacroProcessor.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
-using Dalamud.Plugin;
+using Dalamud.Logging;
namespace Dalamud.Interface.Internal.Scratchpad
{
diff --git a/Dalamud/Interface/Internal/UiDebug.cs b/Dalamud/Interface/Internal/UiDebug.cs
index 3e7310633..3a2847b99 100644
--- a/Dalamud/Interface/Internal/UiDebug.cs
+++ b/Dalamud/Interface/Internal/UiDebug.cs
@@ -273,8 +273,11 @@ namespace Dalamud.Interface.Internal
ImGui.Text($"texture type: {texType} part_id={imageNode->PartId} part_id_count={imageNode->PartsList->PartCount}");
if (texType == TextureType.Resource)
{
- var texFileNamePtr = textureInfo->AtkTexture.Resource->TexFileResourceHandle->ResourceHandle.FileName;
- var texString = Marshal.PtrToStringAnsi(new IntPtr(texFileNamePtr));
+ var texFileNameStdString = &textureInfo->AtkTexture.Resource->TexFileResourceHandle->ResourceHandle.FileName;
+ var texString = texFileNameStdString->Length < 16
+ ? Marshal.PtrToStringAnsi((IntPtr)texFileNameStdString->Buffer)
+ : Marshal.PtrToStringAnsi((IntPtr)texFileNameStdString->BufferPtr);
+
ImGui.Text($"texture path: {texString}");
var kernelTexture = textureInfo->AtkTexture.Resource->KernelTextureObject;
@@ -327,7 +330,7 @@ namespace Dalamud.Interface.Internal
var childCount = componentInfo.NodeListCount;
- var objectInfo = (ULDComponentInfo*)componentInfo.Objects;
+ var objectInfo = (AtkUldComponentInfo*)componentInfo.Objects;
if (ImGui.TreeNode($"{treePrefix}{objectInfo->ComponentType} Component Node (ptr = {(long)node:X}, component ptr = {(long)compNode->Component:X}) child count = {childCount} ###{(long)node}"))
{
if (ImGui.IsItemHovered())
diff --git a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs
index 92aa1a0c9..f9aa2c901 100644
--- a/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/ConsoleWindow.cs
@@ -6,10 +6,9 @@ using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
-using Dalamud.Configuration.Internal;
-using Dalamud.Game.Command;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Windowing;
+using Dalamud.Logging.Internal;
using ImGuiNET;
using Serilog;
using Serilog.Events;
@@ -307,7 +306,7 @@ namespace Dalamud.Interface.Internal.Windows
try
{
this.historyPos = -1;
- for (int i = this.history.Count - 1; i >= 0; i--)
+ for (var i = this.history.Count - 1; i >= 0; i--)
{
if (this.history[i] == this.commandText)
{
diff --git a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs
index 3b6d97bb2..f5d34b90f 100644
--- a/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs
+++ b/Dalamud/Interface/Internal/Windows/PluginInstallerWindow.cs
@@ -14,6 +14,7 @@ using CheapLoc;
using Dalamud.Interface.Colors;
using Dalamud.Interface.Components;
using Dalamud.Interface.Windowing;
+using Dalamud.Logging.Internal;
using Dalamud.Plugin;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Exceptions;
diff --git a/Dalamud/Interface/Windowing/WindowSystem.cs b/Dalamud/Interface/Windowing/WindowSystem.cs
index f13797a17..608cd3c15 100644
--- a/Dalamud/Interface/Windowing/WindowSystem.cs
+++ b/Dalamud/Interface/Windowing/WindowSystem.cs
@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using ImGuiNET;
-using Serilog;
namespace Dalamud.Interface.Windowing
{
diff --git a/Dalamud/ModuleLog.cs b/Dalamud/Logging/Internal/ModuleLog.cs
similarity index 99%
rename from Dalamud/ModuleLog.cs
rename to Dalamud/Logging/Internal/ModuleLog.cs
index b78430a92..9ec951cad 100644
--- a/Dalamud/ModuleLog.cs
+++ b/Dalamud/Logging/Internal/ModuleLog.cs
@@ -1,6 +1,6 @@
using System;
-namespace Dalamud
+namespace Dalamud.Logging.Internal
{
///
/// Class offering various methods to allow for logging in Dalamud modules.
diff --git a/Dalamud/Interface/Internal/SerilogEventSink.cs b/Dalamud/Logging/Internal/SerilogEventSink.cs
similarity index 97%
rename from Dalamud/Interface/Internal/SerilogEventSink.cs
rename to Dalamud/Logging/Internal/SerilogEventSink.cs
index ac2c522ba..518e6edca 100644
--- a/Dalamud/Interface/Internal/SerilogEventSink.cs
+++ b/Dalamud/Logging/Internal/SerilogEventSink.cs
@@ -3,7 +3,7 @@ using System;
using Serilog.Core;
using Serilog.Events;
-namespace Dalamud.Interface.Internal
+namespace Dalamud.Logging.Internal
{
///
/// Serilog event sink.
diff --git a/Dalamud/Logging/PluginLog.cs b/Dalamud/Logging/PluginLog.cs
new file mode 100644
index 000000000..fefb386c5
--- /dev/null
+++ b/Dalamud/Logging/PluginLog.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Reflection;
+
+namespace Dalamud.Logging
+{
+ ///
+ /// Class offering various static methods to allow for logging in plugins.
+ ///
+ public static class PluginLog
+ {
+ ///
+ /// Log a templated verbose message to the in-game debug log.
+ ///
+ /// The message template.
+ /// Values to log.
+ public static void Verbose(string messageTemplate, params object[] values)
+ => Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated verbose message to the in-game debug log.
+ ///
+ /// The exception that caused the error.
+ /// The message template.
+ /// Values to log.
+ public static void Verbose(Exception exception, string messageTemplate, params object[] values)
+ => Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated debug message to the in-game debug log.
+ ///
+ /// The message template.
+ /// Values to log.
+ public static void Debug(string messageTemplate, params object[] values)
+ => Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated debug message to the in-game debug log.
+ ///
+ /// The exception that caused the error.
+ /// The message template.
+ /// Values to log.
+ public static void Debug(Exception exception, string messageTemplate, params object[] values)
+ => Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated information message to the in-game debug log.
+ ///
+ /// The message template.
+ /// Values to log.
+ public static void Information(string messageTemplate, params object[] values)
+ => Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated information message to the in-game debug log.
+ ///
+ /// The exception that caused the error.
+ /// The message template.
+ /// Values to log.
+ public static void Information(Exception exception, string messageTemplate, params object[] values)
+ => Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated warning message to the in-game debug log.
+ ///
+ /// The message template.
+ /// Values to log.
+ public static void Warning(string messageTemplate, params object[] values)
+ => Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated warning message to the in-game debug log.
+ ///
+ /// The exception that caused the error.
+ /// The message template.
+ /// Values to log.
+ public static void Warning(Exception exception, string messageTemplate, params object[] values)
+ => Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated error message to the in-game debug log.
+ ///
+ /// The message template.
+ /// Values to log.
+ public static void Error(string messageTemplate, params object[] values)
+ => Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {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 static void Error(Exception exception, string messageTemplate, params object[] values)
+ => Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated fatal message to the in-game debug log.
+ ///
+ /// The message template.
+ /// Values to log.
+ public static void Fatal(string messageTemplate, params object[] values)
+ => Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+
+ ///
+ /// Log a templated fatal message to the in-game debug log.
+ ///
+ /// The exception that caused the error.
+ /// The message template.
+ /// Values to log.
+ public static void Fatal(Exception exception, string messageTemplate, params object[] values)
+ => Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
+ }
+}
diff --git a/Dalamud/Plugin/DalamudPluginInterface.cs b/Dalamud/Plugin/DalamudPluginInterface.cs
index 9ab55d24c..8814e494a 100644
--- a/Dalamud/Plugin/DalamudPluginInterface.cs
+++ b/Dalamud/Plugin/DalamudPluginInterface.cs
@@ -347,35 +347,6 @@ namespace Dalamud.Plugin
#endregion
- #region Logging
-
- ///
- /// Log a templated message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- [Obsolete("Use PluginLog")]
- 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.
- [Obsolete("Use PluginLog")]
- 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.
- [Obsolete("Use PluginLog")]
- public void LogError(Exception exception, string messageTemplate, params object[] values) => Serilog.Log.Error(exception, messageTemplate, values);
-
- #endregion
-
///
/// Unregister your plugin and dispose all references. You have to call this when your IDalamudPlugin is disposed.
///
diff --git a/Dalamud/Plugin/Internal/LocalDevPlugin.cs b/Dalamud/Plugin/Internal/LocalDevPlugin.cs
index 77b3be253..f874267a8 100644
--- a/Dalamud/Plugin/Internal/LocalDevPlugin.cs
+++ b/Dalamud/Plugin/Internal/LocalDevPlugin.cs
@@ -1,10 +1,10 @@
using System;
using System.IO;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Configuration.Internal;
+using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Types;
namespace Dalamud.Plugin.Internal
diff --git a/Dalamud/Plugin/Internal/LocalPlugin.cs b/Dalamud/Plugin/Internal/LocalPlugin.cs
index f7bbe9615..f5b3481f8 100644
--- a/Dalamud/Plugin/Internal/LocalPlugin.cs
+++ b/Dalamud/Plugin/Internal/LocalPlugin.cs
@@ -3,8 +3,8 @@ using System.IO;
using System.Linq;
using System.Reflection;
-using Dalamud.Configuration.Internal;
using Dalamud.Game;
+using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Exceptions;
using Dalamud.Plugin.Internal.Types;
using McMaster.NETCore.Plugins;
diff --git a/Dalamud/Plugin/Internal/PluginManager.cs b/Dalamud/Plugin/Internal/PluginManager.cs
index 5f1165742..a3f4f250e 100644
--- a/Dalamud/Plugin/Internal/PluginManager.cs
+++ b/Dalamud/Plugin/Internal/PluginManager.cs
@@ -14,6 +14,7 @@ using System.Threading.Tasks;
using CheapLoc;
using Dalamud.Configuration;
using Dalamud.Game.Text;
+using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Exceptions;
using Dalamud.Plugin.Internal.Types;
using HarmonyLib;
diff --git a/Dalamud/Plugin/Internal/PluginRepository.cs b/Dalamud/Plugin/Internal/PluginRepository.cs
index 64769322d..e76aa67d1 100644
--- a/Dalamud/Plugin/Internal/PluginRepository.cs
+++ b/Dalamud/Plugin/Internal/PluginRepository.cs
@@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
-using System.Linq;
using System.Net;
using System.Threading.Tasks;
+using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Types;
using Newtonsoft.Json;
diff --git a/Dalamud/Plugin/PluginLog.cs b/Dalamud/Plugin/PluginLog.cs
deleted file mode 100644
index 3bfa0d904..000000000
--- a/Dalamud/Plugin/PluginLog.cs
+++ /dev/null
@@ -1,240 +0,0 @@
-using System;
-using System.Reflection;
-
-namespace Dalamud.Plugin
-{
- ///
- /// Class offering various static methods to allow for logging in plugins.
- ///
- public static class PluginLog
- {
- #region "Log" prefixed Serilog style methods
-
- ///
- /// Log a templated message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Log(string messageTemplate, params object[] values)
- => Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void Log(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated verbose message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void LogVerbose(string messageTemplate, params object[] values)
- => Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated verbose message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void LogVerbose(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated debug message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void LogDebug(string messageTemplate, params object[] values)
- => Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated debug message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void LogDebug(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated information message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void LogInformation(string messageTemplate, params object[] values)
- => Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated information message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void LogInformation(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated warning message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void LogWarning(string messageTemplate, params object[] values)
- => Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated warning message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void LogWarning(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated error message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void LogError(string messageTemplate, params object[] values)
- => Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {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 static void LogError(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated fatal message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void LogFatal(string messageTemplate, params object[] values)
- => Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated fatal message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void LogFatal(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- #endregion
-
- #region Serilog style methods
-
- ///
- /// Log a templated verbose message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Verbose(string messageTemplate, params object[] values)
- => Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated verbose message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void Verbose(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated debug message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Debug(string messageTemplate, params object[] values)
- => Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated debug message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void Debug(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated information message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Information(string messageTemplate, params object[] values)
- => Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated information message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void Information(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated warning message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Warning(string messageTemplate, params object[] values)
- => Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated warning message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void Warning(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated error message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Error(string messageTemplate, params object[] values)
- => Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {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 static void Error(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated fatal message to the in-game debug log.
- ///
- /// The message template.
- /// Values to log.
- public static void Fatal(string messageTemplate, params object[] values)
- => Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- ///
- /// Log a templated fatal message to the in-game debug log.
- ///
- /// The exception that caused the error.
- /// The message template.
- /// Values to log.
- public static void Fatal(Exception exception, string messageTemplate, params object[] values)
- => Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
-
- #endregion
- }
-}
diff --git a/Dalamud/corehook64.dll b/Dalamud/corehook64.dll
deleted file mode 100644
index 9b21a40d1..000000000
Binary files a/Dalamud/corehook64.dll and /dev/null differ
diff --git a/build/build.csproj b/build/build.csproj
index b5403f5ce..a9b6c7ef0 100644
--- a/build/build.csproj
+++ b/build/build.csproj
@@ -9,6 +9,6 @@
..
-
+
diff --git a/lib/FFXIVClientStructs b/lib/FFXIVClientStructs
index e3bec1189..cbbea8ea9 160000
--- a/lib/FFXIVClientStructs
+++ b/lib/FFXIVClientStructs
@@ -1 +1 @@
-Subproject commit e3bec118909b0eafdd0ee7c3312c646ce0c3f3dd
+Subproject commit cbbea8ea911dda876d4a996f214f337e4db88a01
diff --git a/lib/ImGuiScene b/lib/ImGuiScene
index 372419027..c6ed214c2 160000
--- a/lib/ImGuiScene
+++ b/lib/ImGuiScene
@@ -1 +1 @@
-Subproject commit 3724190279a24f638c9627688a837f9b61457668
+Subproject commit c6ed214c2f7b269c007e5f7f70788745e45e9eb3
diff --git a/lib/SharpDX.Desktop b/lib/SharpDX.Desktop
deleted file mode 160000
index 7fc56bc0a..000000000
--- a/lib/SharpDX.Desktop
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 7fc56bc0a240030d4736e6b16da33b08c73c3ba4