mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-15 05:04:15 +01:00
Merge branch 'master' of https://github.com/goatcorp/Dalamud
This commit is contained in:
commit
459e401f90
51 changed files with 791 additions and 552 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -4,6 +4,3 @@
|
||||||
[submodule "lib/FFXIVClientStructs"]
|
[submodule "lib/FFXIVClientStructs"]
|
||||||
path = lib/FFXIVClientStructs
|
path = lib/FFXIVClientStructs
|
||||||
url = https://github.com/goatcorp/FFXIVClientStructs.git
|
url = https://github.com/goatcorp/FFXIVClientStructs.git
|
||||||
[submodule "lib/SharpDX.Desktop"]
|
|
||||||
path = lib/SharpDX.Desktop
|
|
||||||
url = https://github.com/goatcorp/SharpDX.Desktop.git
|
|
||||||
|
|
|
||||||
|
|
@ -11,23 +11,22 @@
|
||||||
<NoWarn>IDE0003</NoWarn>
|
<NoWarn>IDE0003</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Label="Build">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<OutputPath>$(AppData)\XIVLauncher\devPlugins\Dalamud.CorePlugin</OutputPath>
|
||||||
<DebugType>full</DebugType>
|
|
||||||
<Optimize>false</Optimize>
|
|
||||||
<OutputPath>$(appData)\XIVLauncher\devPlugins\</OutputPath>
|
|
||||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
<ErrorReport>prompt</ErrorReport>
|
<ErrorReport>prompt</ErrorReport>
|
||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' " Label="Build">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " Label="Build">
|
||||||
<DebugType>pdbonly</DebugType>
|
<DebugType>pdbonly</DebugType>
|
||||||
<Optimize>true</Optimize>
|
<Optimize>true</Optimize>
|
||||||
<OutputPath>$(appData)\XIVLauncher\devPlugins\</OutputPath>
|
|
||||||
<DefineConstants>TRACE</DefineConstants>
|
|
||||||
<ErrorReport>prompt</ErrorReport>
|
|
||||||
<WarningLevel>4</WarningLevel>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
using Dalamud.Logging;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
|
|
||||||
namespace Dalamud.CorePlugin
|
namespace Dalamud.CorePlugin
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,6 @@ namespace Dalamud.CorePlugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal class PluginWindow : Window, IDisposable
|
internal class PluginWindow : Window, IDisposable
|
||||||
{
|
{
|
||||||
private static readonly ModuleLog Log = new("CorePlugin");
|
|
||||||
|
|
||||||
private readonly Dalamud dalamud;
|
private readonly Dalamud dalamud;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -20,13 +18,13 @@ namespace Dalamud.CorePlugin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dalamud">The Dalamud instance.</param>
|
/// <param name="dalamud">The Dalamud instance.</param>
|
||||||
public PluginWindow(Dalamud dalamud)
|
public PluginWindow(Dalamud dalamud)
|
||||||
: base("CorePlugin", ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoScrollbar)
|
: base("CorePlugin")
|
||||||
{
|
{
|
||||||
this.dalamud = dalamud;
|
this.dalamud = dalamud;
|
||||||
this.IsOpen = true;
|
this.IsOpen = true;
|
||||||
|
|
||||||
this.Size = new Vector2(810, 520);
|
this.Size = new Vector2(810, 520);
|
||||||
this.SizeCondition = ImGuiCond.Always;
|
this.SizeCondition = ImGuiCond.FirstUseEver;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Label="Warnings">
|
<PropertyGroup Label="Warnings">
|
||||||
<NoWarn>IDE1006;CS1591;CS1701;CS1702</NoWarn>
|
<NoWarn>IDE0003;IDE0044;IDE1006;CS1591;CS1701;CS1702</NoWarn>
|
||||||
|
<!-- IDE0003 - Name can be simplified -->
|
||||||
<!-- IDE1006 - Naming violation -->
|
<!-- IDE1006 - Naming violation -->
|
||||||
<!-- CS1591 - Missing XML comment for publicly visible type or member -->
|
<!-- CS1591 - Missing XML comment for publicly visible type or member -->
|
||||||
<!-- CS1701 - Runtime policy may be needed -->
|
<!-- CS1701 - Runtime policy may be needed -->
|
||||||
|
|
@ -59,9 +60,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Iced" Version="1.12.0" />
|
<PackageReference Include="Iced" Version="1.13.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="PeNet" Version="2.6.3" />
|
<PackageReference Include="PeNet" Version="2.6.4" />
|
||||||
<PackageReference Include="Reloaded.Memory" Version="4.1.1" />
|
<PackageReference Include="Reloaded.Memory" Version="4.1.1" />
|
||||||
<PackageReference Include="Reloaded.Memory.Buffers" Version="1.3.5" />
|
<PackageReference Include="Reloaded.Memory.Buffers" Version="1.3.5" />
|
||||||
<PackageReference Include="Serilog" Version="2.10.0" />
|
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||||
|
|
@ -84,6 +85,5 @@
|
||||||
<Compile Include="..\Dalamud\DalamudStartInfo.cs" />
|
<Compile Include="..\Dalamud\DalamudStartInfo.cs" />
|
||||||
<Compile Include="..\Dalamud\Game\GameVersion.cs" />
|
<Compile Include="..\Dalamud\Game\GameVersion.cs" />
|
||||||
<Compile Include="..\Dalamud\Game\GameVersionConverter.cs" />
|
<Compile Include="..\Dalamud\Game\GameVersionConverter.cs" />
|
||||||
<Compile Include="..\Dalamud\Interface\Internal\SerilogEventSink.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
using Dalamud.Interface.Internal;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Reloaded.Memory.Buffers;
|
using Reloaded.Memory.Buffers;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
@ -129,13 +128,58 @@ namespace Dalamud.Injector
|
||||||
levelSwitch.MinimumLevel = LogEventLevel.Information;
|
levelSwitch.MinimumLevel = LogEventLevel.Information;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
CullLogFile(logPath, 1 * 1024 * 1024);
|
||||||
|
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.WriteTo.Async(a => a.File(logPath))
|
.WriteTo.Async(a => a.File(logPath))
|
||||||
.WriteTo.Sink(SerilogEventSink.Instance)
|
|
||||||
.MinimumLevel.ControlledBy(levelSwitch)
|
.MinimumLevel.ControlledBy(levelSwitch)
|
||||||
.CreateLogger();
|
.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)
|
private static Process GetProcess(string arg)
|
||||||
{
|
{
|
||||||
Process process;
|
Process process;
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ using PeNet.Header.Pe;
|
||||||
using Reloaded.Memory.Buffers;
|
using Reloaded.Memory.Buffers;
|
||||||
using Reloaded.Memory.Sources;
|
using Reloaded.Memory.Sources;
|
||||||
using Reloaded.Memory.Utilities;
|
using Reloaded.Memory.Utilities;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
using static Dalamud.Injector.NativeFunctions;
|
using static Dalamud.Injector.NativeFunctions;
|
||||||
using static Iced.Intel.AssemblerRegisters;
|
using static Iced.Intel.AssemblerRegisters;
|
||||||
|
|
@ -27,7 +28,7 @@ namespace Dalamud.Injector
|
||||||
private readonly Process targetProcess;
|
private readonly Process targetProcess;
|
||||||
private readonly ExternalMemory extMemory;
|
private readonly ExternalMemory extMemory;
|
||||||
private readonly CircularBuffer circularBuffer;
|
private readonly CircularBuffer circularBuffer;
|
||||||
private readonly PrivateMemoryBuffer privateBuffer;
|
private readonly PrivateMemoryBuffer memoryBuffer;
|
||||||
|
|
||||||
private IntPtr loadLibraryShellPtr;
|
private IntPtr loadLibraryShellPtr;
|
||||||
private IntPtr loadLibraryRetPtr;
|
private IntPtr loadLibraryRetPtr;
|
||||||
|
|
@ -45,7 +46,7 @@ namespace Dalamud.Injector
|
||||||
|
|
||||||
this.extMemory = new ExternalMemory(targetProcess);
|
this.extMemory = new ExternalMemory(targetProcess);
|
||||||
this.circularBuffer = new CircularBuffer(4096, this.extMemory);
|
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");
|
using var kernel32Module = this.GetProcessModule("KERNEL32.DLL");
|
||||||
var kernel32PeFile = new PeFile(kernel32Module.FileName);
|
var kernel32PeFile = new PeFile(kernel32Module.FileName);
|
||||||
|
|
@ -67,7 +68,7 @@ namespace Dalamud.Injector
|
||||||
|
|
||||||
this.targetProcess?.Dispose();
|
this.targetProcess?.Dispose();
|
||||||
this.circularBuffer?.Dispose();
|
this.circularBuffer?.Dispose();
|
||||||
this.privateBuffer?.Dispose();
|
this.memoryBuffer?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -82,6 +83,8 @@ namespace Dalamud.Injector
|
||||||
if (lpParameter == IntPtr.Zero)
|
if (lpParameter == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate LoadLibraryW parameter");
|
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(
|
var threadHandle = CreateRemoteThread(
|
||||||
this.targetProcess.Handle,
|
this.targetProcess.Handle,
|
||||||
IntPtr.Zero,
|
IntPtr.Zero,
|
||||||
|
|
@ -93,7 +96,7 @@ namespace Dalamud.Injector
|
||||||
|
|
||||||
_ = WaitForSingleObject(threadHandle, uint.MaxValue);
|
_ = WaitForSingleObject(threadHandle, uint.MaxValue);
|
||||||
|
|
||||||
this.extMemory.Read(this.loadLibraryRetPtr, out address);
|
address = this.extMemory.Read<IntPtr>(this.loadLibraryRetPtr);
|
||||||
|
|
||||||
if (address == IntPtr.Zero)
|
if (address == IntPtr.Zero)
|
||||||
throw new Exception($"Error calling LoadLibraryW with {modulePath}");
|
throw new Exception($"Error calling LoadLibraryW with {modulePath}");
|
||||||
|
|
@ -107,7 +110,8 @@ namespace Dalamud.Injector
|
||||||
/// <param name="address">Address to the function.</param>
|
/// <param name="address">Address to the function.</param>
|
||||||
public void GetFunctionAddress(IntPtr module, string functionName, out IntPtr address)
|
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);
|
var lpParameter = this.circularBuffer.Add(ref getProcAddressParams);
|
||||||
|
|
||||||
if (lpParameter == IntPtr.Zero)
|
if (lpParameter == IntPtr.Zero)
|
||||||
|
|
@ -151,19 +155,25 @@ namespace Dalamud.Injector
|
||||||
_ = WaitForSingleObject(threadHandle, uint.MaxValue);
|
_ = WaitForSingleObject(threadHandle, uint.MaxValue);
|
||||||
|
|
||||||
GetExitCodeThread(threadHandle, out exitCode);
|
GetExitCodeThread(threadHandle, out exitCode);
|
||||||
|
|
||||||
|
CloseHandle(threadHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupLoadLibrary(ProcessModule kernel32Module, ExportFunction[] kernel32Exports)
|
private void SetupLoadLibrary(ProcessModule kernel32Module, ExportFunction[] kernel32Exports)
|
||||||
{
|
{
|
||||||
var offset = this.GetExportedFunctionOffset(kernel32Exports, "LoadLibraryW");
|
var offset = this.GetExportedFunctionOffset(kernel32Exports, "LoadLibraryW");
|
||||||
var functionAddr = kernel32Module.BaseAddress + (int)offset;
|
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)
|
if (functionPtr == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate LoadLibraryW function ptr");
|
throw new Exception("Unable to allocate LoadLibraryW function ptr");
|
||||||
|
|
||||||
var dummy = 0L;
|
var dummy = IntPtr.Zero;
|
||||||
this.loadLibraryRetPtr = this.privateBuffer.Add(ref dummy);
|
this.loadLibraryRetPtr = this.memoryBuffer.Add(ref dummy);
|
||||||
|
Log.Verbose($"LoadLibraryRetPtr: 0x{this.loadLibraryRetPtr.ToInt64():X}");
|
||||||
|
|
||||||
if (this.loadLibraryRetPtr == IntPtr.Zero)
|
if (this.loadLibraryRetPtr == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate LoadLibraryW return value");
|
throw new Exception("Unable to allocate LoadLibraryW return value");
|
||||||
|
|
@ -180,23 +190,41 @@ namespace Dalamud.Injector
|
||||||
asm.ret(); // ret // Restore stack ptr. (Callee cleanup)
|
asm.ret(); // ret // Restore stack ptr. (Callee cleanup)
|
||||||
|
|
||||||
var bytes = this.Assemble(asm);
|
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)
|
if (this.loadLibraryShellPtr == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate LoadLibraryW shellcode");
|
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<IntPtr>(functionPtr);
|
||||||
|
Log.Verbose($"LoadLibraryPtr: {this.GetResultMarker(outFunctionPtr == functionAddr)}");
|
||||||
|
|
||||||
|
var outRetPtr = this.extMemory.Read<IntPtr>(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)
|
private void SetupGetProcAddress(ProcessModule kernel32Module, ExportFunction[] kernel32Exports)
|
||||||
{
|
{
|
||||||
var offset = this.GetExportedFunctionOffset(kernel32Exports, "GetProcAddress");
|
var offset = this.GetExportedFunctionOffset(kernel32Exports, "GetProcAddress");
|
||||||
var functionAddr = kernel32Module.BaseAddress + (int)offset;
|
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)
|
if (functionPtr == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate GetProcAddress function ptr");
|
throw new Exception("Unable to allocate GetProcAddress function ptr");
|
||||||
|
|
||||||
var dummy = 0L;
|
var dummy = IntPtr.Zero;
|
||||||
this.getProcAddressRetPtr = this.privateBuffer.Add(ref dummy);
|
this.getProcAddressRetPtr = this.memoryBuffer.Add(ref dummy);
|
||||||
|
Log.Verbose($"GetProcAddressRetPtr: 0x{this.loadLibraryRetPtr.ToInt64():X}");
|
||||||
|
|
||||||
if (this.getProcAddressRetPtr == IntPtr.Zero)
|
if (this.getProcAddressRetPtr == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate GetProcAddress return value");
|
throw new Exception("Unable to allocate GetProcAddress return value");
|
||||||
|
|
@ -215,10 +243,24 @@ namespace Dalamud.Injector
|
||||||
asm.ret(); // ret // Restore stack ptr. (Callee cleanup)
|
asm.ret(); // ret // Restore stack ptr. (Callee cleanup)
|
||||||
|
|
||||||
var bytes = this.Assemble(asm);
|
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)
|
if (this.getProcAddressShellPtr == IntPtr.Zero)
|
||||||
throw new Exception("Unable to allocate GetProcAddress shellcode");
|
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<IntPtr>(functionPtr);
|
||||||
|
Log.Verbose($"GetProcAddressPtr: {this.GetResultMarker(outFunctionPtr == functionAddr)}");
|
||||||
|
|
||||||
|
var outRetPtr = this.extMemory.Read<IntPtr>(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)
|
private byte[] Assemble(Assembler assembler)
|
||||||
|
|
@ -264,28 +306,42 @@ namespace Dalamud.Injector
|
||||||
return exportFunction.Address;
|
return exportFunction.Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IntPtr WriteNullTerminatedASCIIString(string libraryPath)
|
private IntPtr WriteNullTerminatedASCIIString(string value)
|
||||||
{
|
{
|
||||||
var libraryNameBytes = Encoding.ASCII.GetBytes(libraryPath + '\0');
|
var bytes = Encoding.ASCII.GetBytes(value + '\0');
|
||||||
var value = this.circularBuffer.Add(libraryNameBytes);
|
var address = this.circularBuffer.Add(bytes);
|
||||||
|
|
||||||
if (value == IntPtr.Zero)
|
if (address == IntPtr.Zero)
|
||||||
throw new Exception("Unable to write ASCII string to buffer");
|
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 bytes = Encoding.Unicode.GetBytes(value + '\0');
|
||||||
var value = this.circularBuffer.Add(libraryNameBytes);
|
var address = this.circularBuffer.Add(bytes);
|
||||||
|
|
||||||
if (value == IntPtr.Zero)
|
if (address == IntPtr.Zero)
|
||||||
throw new Exception("Unable to write Unicode string to buffer");
|
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)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
private struct GetProcAddressParams
|
private struct GetProcAddressParams
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -582,6 +582,22 @@ namespace Dalamud.Injector
|
||||||
WAIT_FAILED = 0xFFFFFFF,
|
WAIT_FAILED = 0xFFFFFFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Closes an open object handle.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="hObject">
|
||||||
|
/// A valid handle to an open object.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// 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.
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static extern bool CloseHandle(IntPtr hObject);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a thread that runs in the virtual address space of another process. Use the CreateRemoteThreadEx function
|
/// 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.
|
/// 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)]
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);
|
public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Opens an existing local process object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dwDesiredAccess">
|
||||||
|
/// 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.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="bInheritHandle">
|
||||||
|
/// If this value is TRUE, processes created by this process will inherit the handle. Otherwise, the processes do not inherit this handle.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="dwProcessId">
|
||||||
|
/// 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.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>
|
||||||
|
/// 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.
|
||||||
|
/// </returns>
|
||||||
|
[DllImport("kernel32.dll", SetLastError = true)]
|
||||||
|
public static extern IntPtr OpenProcess(
|
||||||
|
ProcessAccessFlags dwDesiredAccess,
|
||||||
|
bool bInheritHandle,
|
||||||
|
int dwProcessId);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// See https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex.
|
/// 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.
|
/// Reserves, commits, or changes the state of a region of memory within the virtual address space of a specified process.
|
||||||
|
|
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
using static Dalamud.Injector.NativeFunctions;
|
|
||||||
|
|
||||||
namespace Dalamud.Injector
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Pin an arbitrary string to a remote process.
|
|
||||||
/// </summary>
|
|
||||||
internal class RemotePinnedData : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Process process;
|
|
||||||
private readonly byte[] data;
|
|
||||||
private readonly IntPtr allocAddr;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="RemotePinnedData"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="process">Process to write in.</param>
|
|
||||||
/// <param name="data">Data to write.</param>
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the address of the pinned data.
|
|
||||||
/// </summary>
|
|
||||||
public IntPtr Address => this.allocAddr;
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -47,12 +47,12 @@ namespace Dalamud.Configuration.Internal
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the language code to load Dalamud localization with.
|
/// Gets or sets the language code to load Dalamud localization with.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LanguageOverride { get; set; }
|
public string LanguageOverride { get; set; } = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the last loaded Dalamud version.
|
/// Gets or sets the last loaded Dalamud version.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string LastVersion { get; set; }
|
public string LastVersion { get; set; } = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the chat type used by default for plugin messages.
|
/// Gets or sets the chat type used by default for plugin messages.
|
||||||
|
|
@ -62,17 +62,17 @@ namespace Dalamud.Configuration.Internal
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether or not plugin testing builds should be shown.
|
/// Gets or sets a value indicating whether or not plugin testing builds should be shown.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DoPluginTest { get; set; }
|
public bool DoPluginTest { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether or not Dalamud testing builds should be used.
|
/// Gets or sets a value indicating whether or not Dalamud testing builds should be used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DoDalamudTest { get; set; }
|
public bool DoDalamudTest { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether or not XL should download the Dalamud .NET runtime.
|
/// Gets or sets a value indicating whether or not XL should download the Dalamud .NET runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DoDalamudRuntime { get; set; }
|
public bool DoDalamudRuntime { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a list of custom repos.
|
/// Gets or sets a list of custom repos.
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,9 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CheapLoc" Version="1.1.5" />
|
<PackageReference Include="CheapLoc" Version="1.1.6" />
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2021.1.0" />
|
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" />
|
||||||
<PackageReference Include="Lib.Harmony" Version="2.1.0" />
|
<PackageReference Include="Lib.Harmony" Version="2.1.1" />
|
||||||
<PackageReference Include="Lumina" Version="3.3.0" />
|
<PackageReference Include="Lumina" Version="3.3.0" />
|
||||||
<PackageReference Include="Lumina.Excel" Version="5.50.0" />
|
<PackageReference Include="Lumina.Excel" Version="5.50.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,14 @@ using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
using Dalamud.Interface.Internal;
|
using Dalamud.Logging.Internal;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Core;
|
using Serilog.Core;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
|
using static Dalamud.NativeFunctions;
|
||||||
|
|
||||||
namespace Dalamud
|
namespace Dalamud
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -43,11 +45,16 @@ namespace Dalamud
|
||||||
/// <param name="info">The <see cref="DalamudStartInfo"/> containing information needed to initialize Dalamud.</param>
|
/// <param name="info">The <see cref="DalamudStartInfo"/> containing information needed to initialize Dalamud.</param>
|
||||||
private static void RunThread(DalamudStartInfo info)
|
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
|
// Load configuration first to get some early persistent state, like log level
|
||||||
var configuration = DalamudConfiguration.Load(info.ConfigurationPath);
|
var configuration = DalamudConfiguration.Load(info.ConfigurationPath);
|
||||||
|
|
||||||
// Setup logger
|
// Set the appropriate logging level from the configuration
|
||||||
var levelSwitch = InitLogging(info.WorkingDirectory, configuration);
|
#if !DEBUG
|
||||||
|
levelSwitch.MinimumLevel = configuration.LogLevel;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Log any unhandled exception.
|
// Log any unhandled exception.
|
||||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||||
|
|
@ -88,23 +95,22 @@ namespace Dalamud
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LoggingLevelSwitch InitLogging(string baseDirectory, DalamudConfiguration configuration)
|
private static LoggingLevelSwitch InitLogging(string baseDirectory)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
var logPath = Path.Combine(baseDirectory, "dalamud.log");
|
var logPath = Path.Combine(baseDirectory, "dalamud.log");
|
||||||
|
var oldPath = Path.Combine(baseDirectory, "dalamud.log.old");
|
||||||
#else
|
#else
|
||||||
var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log");
|
var logPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log");
|
||||||
|
var oldPath = Path.Combine(baseDirectory, "..", "..", "..", "dalamud.log.old");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
var levelSwitch = new LoggingLevelSwitch();
|
CullLogFile(logPath, oldPath, 1 * 1024 * 1024);
|
||||||
|
CullLogFile(oldPath, null, 10 * 1024 * 1024);
|
||||||
|
|
||||||
#if DEBUG
|
var levelSwitch = new LoggingLevelSwitch(LogEventLevel.Verbose);
|
||||||
levelSwitch.MinimumLevel = LogEventLevel.Verbose;
|
|
||||||
#else
|
|
||||||
levelSwitch.MinimumLevel = configuration.LogLevel;
|
|
||||||
#endif
|
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.WriteTo.Async(a => a.File(logPath, fileSizeLimitBytes: 5 * 1024 * 1024, rollOnFileSizeLimit: true))
|
.WriteTo.Async(a => a.File(logPath))
|
||||||
.WriteTo.Sink(SerilogEventSink.Instance)
|
.WriteTo.Sink(SerilogEventSink.Instance)
|
||||||
.MinimumLevel.ControlledBy(levelSwitch)
|
.MinimumLevel.ControlledBy(levelSwitch)
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
@ -112,6 +118,73 @@ namespace Dalamud
|
||||||
return levelSwitch;
|
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)
|
private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
|
||||||
{
|
{
|
||||||
switch (args.ExceptionObject)
|
switch (args.ExceptionObject)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
using Dalamud.Game.Network;
|
||||||
using Dalamud.Hooking;
|
using Dalamud.Hooking;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using Dalamud.Game.Network.Structures;
|
using Dalamud.Game.Network.Structures;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An interface binding for the Universalis uploader.
|
/// An interface binding for the Universalis uploader.
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Dalamud.Game.Network.Structures;
|
||||||
|
|
||||||
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This represents a submission to a marketboard aggregation website.
|
||||||
|
/// </summary>
|
||||||
|
internal class MarketBoardItemRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the catalog ID.
|
||||||
|
/// </summary>
|
||||||
|
public uint CatalogId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the amount to arrive.
|
||||||
|
/// </summary>
|
||||||
|
public byte AmountToArrive { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the offered item listings.
|
||||||
|
/// </summary>
|
||||||
|
public List<MarketBoardCurrentOfferings.MarketBoardItemListing> Listings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the historical item listings.
|
||||||
|
/// </summary>
|
||||||
|
public List<MarketBoardHistory.MarketBoardHistoryListing> History { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the listing request ID.
|
||||||
|
/// </summary>
|
||||||
|
public int ListingsRequestId { get; set; } = -1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the upload is complete.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsDone => this.Listings.Count == this.AmountToArrive && this.History.Count != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -2,7 +2,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Request payload for market board purchases.
|
/// Request payload for market board purchases.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UniversalisItemListingDeleteRequest
|
internal class UniversalisItemListingDeleteRequest
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the object ID of the retainer associated with the sale.
|
/// Gets or sets the object ID of the retainer associated with the sale.
|
||||||
|
|
@ -2,7 +2,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -2,7 +2,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis.Types
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Universalis API structure.
|
/// A Universalis API structure.
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
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.Internal.MarketBoardUploaders.Universalis.Types;
|
||||||
using Dalamud.Game.Network.MarketBoardUploaders.Universalis;
|
|
||||||
using Dalamud.Game.Network.Structures;
|
using Dalamud.Game.Network.Structures;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
|
namespace Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class represents an uploader for contributing data to 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
|
internal class UniversalisMarketBoardUploader : IMarketBoardUploader
|
||||||
{
|
{
|
||||||
private const string ApiBase = "https://universalis.app";
|
private const string ApiBase = "https://universalis.app";
|
||||||
|
|
||||||
// private const string ApiBase = "https://127.0.0.1:443";
|
// private const string ApiBase = "https://127.0.0.1:443";
|
||||||
|
|
||||||
private const string ApiKey = "GGD6RdSfGyRiHM5WDnAo0Nj9Nv7aC5NDhMj3BebT";
|
private const string ApiKey = "GGD6RdSfGyRiHM5WDnAo0Nj9Nv7aC5NDhMj3BebT";
|
||||||
|
|
||||||
private readonly Dalamud dalamud;
|
private readonly Dalamud dalamud;
|
||||||
|
|
@ -34,14 +35,14 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void Upload(MarketBoardItemRequest request)
|
public void Upload(MarketBoardItemRequest request)
|
||||||
{
|
{
|
||||||
using var client = new WebClient();
|
using var client = new HttpClient();
|
||||||
|
|
||||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
|
||||||
|
|
||||||
Log.Verbose("Starting Universalis upload.");
|
Log.Verbose("Starting Universalis upload.");
|
||||||
var uploader = this.dalamud.ClientState.LocalContentId;
|
var uploader = this.dalamud.ClientState.LocalContentId;
|
||||||
|
|
||||||
var listingsRequestObject = new UniversalisItemListingsUploadRequest
|
// ====================================================================================
|
||||||
|
|
||||||
|
var listingsUploadObject = new UniversalisItemListingsUploadRequest
|
||||||
{
|
{
|
||||||
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
|
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
|
||||||
UploaderId = uploader.ToString(),
|
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);
|
var listingPath = "/upload";
|
||||||
Log.Verbose(upload);
|
var listingUpload = JsonConvert.SerializeObject(listingsUploadObject);
|
||||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", upload);
|
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,
|
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
|
||||||
UploaderId = uploader.ToString(),
|
UploaderId = uploader.ToString(),
|
||||||
|
|
@ -93,7 +97,7 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
|
||||||
|
|
||||||
foreach (var marketBoardHistoryListing in request.History)
|
foreach (var marketBoardHistoryListing in request.History)
|
||||||
{
|
{
|
||||||
historyRequestObject.Entries.Add(new UniversalisHistoryEntry
|
historyUploadObject.Entries.Add(new UniversalisHistoryEntry
|
||||||
{
|
{
|
||||||
BuyerName = marketBoardHistoryListing.BuyerName,
|
BuyerName = marketBoardHistoryListing.BuyerName,
|
||||||
Hq = marketBoardHistoryListing.IsHq,
|
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);
|
Log.Verbose("Universalis data upload for item#{0} completed.", request.CatalogId);
|
||||||
}
|
}
|
||||||
|
|
@ -116,9 +121,11 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public void UploadTax(MarketTaxRates taxRates)
|
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,
|
WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0,
|
||||||
UploaderId = this.dalamud.ClientState.LocalContentId.ToString(),
|
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);
|
client.PostAsync($"{ApiBase}{taxPath}/{ApiKey}", new StringContent(taxUpload, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
|
||||||
Log.Verbose(historyUpload);
|
|
||||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
|
// ====================================================================================
|
||||||
|
|
||||||
Log.Verbose("Universalis tax upload completed.");
|
Log.Verbose("Universalis tax upload completed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
/// <remarks>
|
||||||
|
/// 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.
|
||||||
|
/// </remarks>
|
||||||
public void UploadPurchase(MarketBoardPurchaseHandler purchaseHandler)
|
public void UploadPurchase(MarketBoardPurchaseHandler purchaseHandler)
|
||||||
{
|
{
|
||||||
using var client = new WebClient();
|
using var client = new HttpClient();
|
||||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
|
||||||
client.Headers.Add(HttpRequestHeader.Authorization, ApiKey);
|
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(ApiKey);
|
||||||
|
|
||||||
var itemId = purchaseHandler.CatalogId;
|
var itemId = purchaseHandler.CatalogId;
|
||||||
var worldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
var worldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||||
|
|
||||||
var purchaseRequest = new UniversalisItemListingDeleteRequest
|
// ====================================================================================
|
||||||
|
|
||||||
|
var deleteListingObject = new UniversalisItemListingDeleteRequest
|
||||||
{
|
{
|
||||||
PricePerUnit = purchaseHandler.PricePerUnit,
|
PricePerUnit = purchaseHandler.PricePerUnit,
|
||||||
Quantity = purchaseHandler.ItemQuantity,
|
Quantity = purchaseHandler.ItemQuantity,
|
||||||
|
|
@ -161,11 +177,13 @@ namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
|
||||||
UploaderId = this.dalamud.ClientState.LocalContentId.ToString(),
|
UploaderId = this.dalamud.ClientState.LocalContentId.ToString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
var requestPath = ApiBase + $"/api/{worldId}/{itemId}/delete";
|
var deletePath = $"/api/{worldId}/{itemId}/delete";
|
||||||
var purchaseUpload = JsonConvert.SerializeObject(purchaseRequest);
|
var deleteListing = JsonConvert.SerializeObject(deleteListingObject);
|
||||||
Log.Verbose($"Making request to {requestPath}");
|
Log.Verbose($"{deletePath}: {deleteListing}");
|
||||||
Log.Verbose(purchaseUpload);
|
|
||||||
client.UploadString(requestPath, "POST", purchaseUpload);
|
client.PostAsync($"{ApiBase}{deletePath}", new StringContent(deleteListing, Encoding.UTF8, "application/json")).GetAwaiter().GetResult();
|
||||||
|
|
||||||
|
// ====================================================================================
|
||||||
|
|
||||||
Log.Verbose("Universalis purchase upload completed.");
|
Log.Verbose("Universalis purchase upload completed.");
|
||||||
}
|
}
|
||||||
|
|
@ -5,14 +5,13 @@ using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dalamud.Game.Internal.Network;
|
using Dalamud.Game.Network.Internal.MarketBoardUploaders;
|
||||||
using Dalamud.Game.Network.MarketBoardUploaders;
|
using Dalamud.Game.Network.Internal.MarketBoardUploaders.Universalis;
|
||||||
using Dalamud.Game.Network.Structures;
|
using Dalamud.Game.Network.Structures;
|
||||||
using Dalamud.Game.Network.Universalis.MarketBoardUploaders;
|
|
||||||
using Lumina.Excel.GeneratedSheets;
|
using Lumina.Excel.GeneratedSheets;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network
|
namespace Dalamud.Game.Network.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class handles network notifications and uploading market board data.
|
/// 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);
|
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}");
|
Log.Error($"Market Board data arrived without a corresponding request: item#{listing.ItemListings[0].CatalogId}");
|
||||||
return;
|
return;
|
||||||
|
|
@ -207,17 +206,15 @@ namespace Dalamud.Game.Network
|
||||||
|
|
||||||
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);
|
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);
|
||||||
|
|
||||||
if (request == null)
|
if (request == default)
|
||||||
{
|
{
|
||||||
Log.Error(
|
Log.Error($"Market Board data arrived without a corresponding request: item#{listing.CatalogId}");
|
||||||
$"Market Board data arrived without a corresponding request: item#{listing.CatalogId}");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.ListingsRequestId != -1)
|
if (request.ListingsRequestId != -1)
|
||||||
{
|
{
|
||||||
Log.Error(
|
Log.Error($"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
|
||||||
$"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,6 +240,7 @@ namespace Dalamud.Game.Network
|
||||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
|
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
|
||||||
{
|
{
|
||||||
var category = (uint)Marshal.ReadInt32(dataPtr);
|
var category = (uint)Marshal.ReadInt32(dataPtr);
|
||||||
|
|
||||||
// Result dialog packet does not contain market tax rates
|
// Result dialog packet does not contain market tax rates
|
||||||
if (category != 720905)
|
if (category != 720905)
|
||||||
{
|
{
|
||||||
|
|
@ -279,9 +277,9 @@ namespace Dalamud.Game.Network
|
||||||
// Transaction succeeded
|
// Transaction succeeded
|
||||||
if (purchase.ItemQuantity == this.marketBoardPurchaseHandler.ItemQuantity
|
if (purchase.ItemQuantity == this.marketBoardPurchaseHandler.ItemQuantity
|
||||||
&& (purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId
|
&& (purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId
|
||||||
|| purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId + 1000000))
|
|| purchase.CatalogId == this.marketBoardPurchaseHandler.CatalogId + 1_000_000))
|
||||||
{ // HQ
|
{ // 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.
|
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));
|
Task.Run(() => this.uploader.UploadPurchase(handler));
|
||||||
}
|
}
|
||||||
|
|
@ -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<MarketBoardCurrentOfferings.MarketBoardItemListing> Listings { get; set; }
|
|
||||||
|
|
||||||
public List<MarketBoardHistory.MarketBoardHistoryListing> History { get; set; }
|
|
||||||
|
|
||||||
public int ListingsRequestId { get; set; } = -1;
|
|
||||||
|
|
||||||
public bool IsDone => this.Listings.Count == this.AmountToArrive && this.History.Count != 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
namespace Dalamud.Game.Internal.Network
|
namespace Dalamud.Game.Network
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This represents the direction of a network message.
|
/// This represents the direction of a network message.
|
||||||
|
|
@ -5,14 +5,43 @@ using System.Text;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.Structures
|
namespace Dalamud.Game.Network.Structures
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class represents the current market board offerings from a game network packet.
|
||||||
|
/// </summary>
|
||||||
public class MarketBoardCurrentOfferings
|
public class MarketBoardCurrentOfferings
|
||||||
{
|
{
|
||||||
public List<MarketBoardItemListing> ItemListings;
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MarketBoardCurrentOfferings"/> class.
|
||||||
|
/// </summary>
|
||||||
|
internal MarketBoardCurrentOfferings()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public int ListingIndexEnd;
|
/// <summary>
|
||||||
public int ListingIndexStart;
|
/// Gets the list of individual item listings.
|
||||||
public int RequestId;
|
/// </summary>
|
||||||
|
public List<MarketBoardItemListing> ItemListings { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the listing end index.
|
||||||
|
/// </summary>
|
||||||
|
public int ListingIndexEnd { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the listing start index.
|
||||||
|
/// </summary>
|
||||||
|
public int ListingIndexStart { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the request ID.
|
||||||
|
/// </summary>
|
||||||
|
public int RequestId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a <see cref="MarketBoardCurrentOfferings"/> object from memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataPtr">Address to read.</param>
|
||||||
|
/// <returns>A new <see cref="MarketBoardCurrentOfferings"/> object.</returns>
|
||||||
public static unsafe MarketBoardCurrentOfferings Read(IntPtr dataPtr)
|
public static unsafe MarketBoardCurrentOfferings Read(IntPtr dataPtr)
|
||||||
{
|
{
|
||||||
var output = new MarketBoardCurrentOfferings();
|
var output = new MarketBoardCurrentOfferings();
|
||||||
|
|
@ -80,32 +109,124 @@ namespace Dalamud.Game.Network.Structures
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class represents the current market board offering of a single item from the <see cref="MarketBoardCurrentOfferings"/> network packet.
|
||||||
|
/// </summary>
|
||||||
public class MarketBoardItemListing
|
public class MarketBoardItemListing
|
||||||
{
|
{
|
||||||
public ulong ArtisanId;
|
/// <summary>
|
||||||
public uint CatalogId;
|
/// Initializes a new instance of the <see cref="MarketBoardItemListing"/> class.
|
||||||
public bool IsHq;
|
/// </summary>
|
||||||
public uint ItemQuantity;
|
internal MarketBoardItemListing()
|
||||||
public DateTime LastReviewTime;
|
{
|
||||||
public ulong ListingId;
|
}
|
||||||
|
|
||||||
public List<ItemMateria> Materia;
|
/// <summary>
|
||||||
public int MateriaCount;
|
/// Gets the artisan ID.
|
||||||
public bool OnMannequin;
|
/// </summary>
|
||||||
public string PlayerName;
|
public ulong ArtisanId { get; internal set; }
|
||||||
public uint PricePerUnit;
|
|
||||||
public int RetainerCityId;
|
|
||||||
public ulong RetainerId;
|
|
||||||
|
|
||||||
public string RetainerName;
|
/// <summary>
|
||||||
public ulong RetainerOwnerId;
|
/// Gets the catalog ID.
|
||||||
public int StainId;
|
/// </summary>
|
||||||
public uint TotalTax;
|
public uint CatalogId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the item is HQ.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsHq { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the item quantity.
|
||||||
|
/// </summary>
|
||||||
|
public uint ItemQuantity { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the time this offering was last reviewed.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime LastReviewTime { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the listing ID.
|
||||||
|
/// </summary>
|
||||||
|
public ulong ListingId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of materia attached to this item.
|
||||||
|
/// </summary>
|
||||||
|
public List<ItemMateria> Materia { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the amount of attached materia.
|
||||||
|
/// </summary>
|
||||||
|
public int MateriaCount { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether this item is on a mannequin.
|
||||||
|
/// </summary>
|
||||||
|
public bool OnMannequin { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the player name.
|
||||||
|
/// </summary>
|
||||||
|
public string PlayerName { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the price per unit.
|
||||||
|
/// </summary>
|
||||||
|
public uint PricePerUnit { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the city ID of the retainer selling the item.
|
||||||
|
/// </summary>
|
||||||
|
public int RetainerCityId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ID of the retainer selling the item.
|
||||||
|
/// </summary>
|
||||||
|
public ulong RetainerId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the retainer.
|
||||||
|
/// </summary>
|
||||||
|
public string RetainerName { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the ID of the retainer's owner.
|
||||||
|
/// </summary>
|
||||||
|
public ulong RetainerOwnerId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the stain or applied dye of the item.
|
||||||
|
/// </summary>
|
||||||
|
public int StainId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the total tax.
|
||||||
|
/// </summary>
|
||||||
|
public uint TotalTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This represents the materia slotted to an <see cref="MarketBoardItemListing"/>.
|
||||||
|
/// </summary>
|
||||||
public class ItemMateria
|
public class ItemMateria
|
||||||
{
|
{
|
||||||
public int Index;
|
/// <summary>
|
||||||
public int MateriaId;
|
/// Initializes a new instance of the <see cref="ItemMateria"/> class.
|
||||||
|
/// </summary>
|
||||||
|
internal ItemMateria()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the materia index.
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the materia ID.
|
||||||
|
/// </summary>
|
||||||
|
public int MateriaId { get; internal set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,38 @@ using System.Text;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.Structures
|
namespace Dalamud.Game.Network.Structures
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class represents the market board history from a game network packet.
|
||||||
|
/// </summary>
|
||||||
public class MarketBoardHistory
|
public class MarketBoardHistory
|
||||||
{
|
{
|
||||||
public uint CatalogId;
|
/// <summary>
|
||||||
public uint CatalogId2;
|
/// Initializes a new instance of the <see cref="MarketBoardHistory"/> class.
|
||||||
|
/// </summary>
|
||||||
|
internal MarketBoardHistory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public List<MarketBoardHistoryListing> HistoryListings;
|
/// <summary>
|
||||||
|
/// Gets the catalog ID.
|
||||||
|
/// </summary>
|
||||||
|
public uint CatalogId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the second catalog ID.
|
||||||
|
/// </summary>
|
||||||
|
public uint CatalogId2 { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of individual item history listings.
|
||||||
|
/// </summary>
|
||||||
|
public List<MarketBoardHistoryListing> HistoryListings { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a <see cref="MarketBoardHistory"/> object from memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataPtr">Address to read.</param>
|
||||||
|
/// <returns>A new <see cref="MarketBoardHistory"/> object.</returns>
|
||||||
public static unsafe MarketBoardHistory Read(IntPtr dataPtr)
|
public static unsafe MarketBoardHistory Read(IntPtr dataPtr)
|
||||||
{
|
{
|
||||||
var output = new MarketBoardHistory();
|
var output = new MarketBoardHistory();
|
||||||
|
|
@ -47,16 +72,52 @@ namespace Dalamud.Game.Network.Structures
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class represents the market board history of a single item from the <see cref="MarketBoardHistory"/> network packet.
|
||||||
|
/// </summary>
|
||||||
public class MarketBoardHistoryListing
|
public class MarketBoardHistoryListing
|
||||||
{
|
{
|
||||||
public string BuyerName;
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MarketBoardHistoryListing"/> class.
|
||||||
|
/// </summary>
|
||||||
|
internal MarketBoardHistoryListing()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public uint CatalogId;
|
/// <summary>
|
||||||
public bool IsHq;
|
/// Gets the buyer's name.
|
||||||
public bool OnMannequin;
|
/// </summary>
|
||||||
public DateTime PurchaseTime;
|
public string BuyerName { get; internal set; }
|
||||||
public uint Quantity;
|
|
||||||
public uint SalePrice;
|
/// <summary>
|
||||||
|
/// Gets the catalog ID.
|
||||||
|
/// </summary>
|
||||||
|
public uint CatalogId { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the item is HQ.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsHq { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a value indicating whether the item is on a mannequin.
|
||||||
|
/// </summary>
|
||||||
|
public bool OnMannequin { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the time of purchase.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime PurchaseTime { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the quantity.
|
||||||
|
/// </summary>
|
||||||
|
public uint Quantity { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the sale price.
|
||||||
|
/// </summary>
|
||||||
|
public uint SalePrice { get; internal set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,53 @@ using System.IO;
|
||||||
|
|
||||||
namespace Dalamud.Game.Network.Structures
|
namespace Dalamud.Game.Network.Structures
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This class represents the market tax rates from a game network packet.
|
||||||
|
/// </summary>
|
||||||
public class MarketTaxRates
|
public class MarketTaxRates
|
||||||
{
|
{
|
||||||
public uint LimsaLominsaTax;
|
/// <summary>
|
||||||
public uint GridaniaTax;
|
/// Initializes a new instance of the <see cref="MarketTaxRates"/> class.
|
||||||
public uint UldahTax;
|
/// </summary>
|
||||||
public uint IshgardTax;
|
internal MarketTaxRates()
|
||||||
public uint KuganeTax;
|
{
|
||||||
public uint CrystariumTax;
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tax rate in Limsa Lominsa.
|
||||||
|
/// </summary>
|
||||||
|
public uint LimsaLominsaTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tax rate in Gridania.
|
||||||
|
/// </summary>
|
||||||
|
public uint GridaniaTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tax rate in Ul'dah.
|
||||||
|
/// </summary>
|
||||||
|
public uint UldahTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tax rate in Ishgard.
|
||||||
|
/// </summary>
|
||||||
|
public uint IshgardTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tax rate in Kugane.
|
||||||
|
/// </summary>
|
||||||
|
public uint KuganeTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the tax rate in the Crystarium.
|
||||||
|
/// </summary>
|
||||||
|
public uint CrystariumTax { get; internal set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read a <see cref="MarketTaxRates"/> object from memory.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dataPtr">Address to read.</param>
|
||||||
|
/// <returns>A new <see cref="MarketTaxRates"/> object.</returns>
|
||||||
public static unsafe MarketTaxRates Read(IntPtr dataPtr)
|
public static unsafe MarketTaxRates Read(IntPtr dataPtr)
|
||||||
{
|
{
|
||||||
var output = new MarketTaxRates();
|
var output = new MarketTaxRates();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Memory;
|
using Dalamud.Memory;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ using System.Runtime.InteropServices;
|
||||||
|
|
||||||
using Dalamud.Interface.Internal.Windows;
|
using Dalamud.Interface.Internal.Windows;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Logging;
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Internal;
|
using Dalamud.Plugin.Internal;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Logging;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal.Scratchpad
|
namespace Dalamud.Interface.Internal.Scratchpad
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -273,8 +273,11 @@ namespace Dalamud.Interface.Internal
|
||||||
ImGui.Text($"texture type: {texType} part_id={imageNode->PartId} part_id_count={imageNode->PartsList->PartCount}");
|
ImGui.Text($"texture type: {texType} part_id={imageNode->PartId} part_id_count={imageNode->PartsList->PartCount}");
|
||||||
if (texType == TextureType.Resource)
|
if (texType == TextureType.Resource)
|
||||||
{
|
{
|
||||||
var texFileNamePtr = textureInfo->AtkTexture.Resource->TexFileResourceHandle->ResourceHandle.FileName;
|
var texFileNameStdString = &textureInfo->AtkTexture.Resource->TexFileResourceHandle->ResourceHandle.FileName;
|
||||||
var texString = Marshal.PtrToStringAnsi(new IntPtr(texFileNamePtr));
|
var texString = texFileNameStdString->Length < 16
|
||||||
|
? Marshal.PtrToStringAnsi((IntPtr)texFileNameStdString->Buffer)
|
||||||
|
: Marshal.PtrToStringAnsi((IntPtr)texFileNameStdString->BufferPtr);
|
||||||
|
|
||||||
ImGui.Text($"texture path: {texString}");
|
ImGui.Text($"texture path: {texString}");
|
||||||
var kernelTexture = textureInfo->AtkTexture.Resource->KernelTextureObject;
|
var kernelTexture = textureInfo->AtkTexture.Resource->KernelTextureObject;
|
||||||
|
|
||||||
|
|
@ -327,7 +330,7 @@ namespace Dalamud.Interface.Internal
|
||||||
|
|
||||||
var childCount = componentInfo.NodeListCount;
|
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.TreeNode($"{treePrefix}{objectInfo->ComponentType} Component Node (ptr = {(long)node:X}, component ptr = {(long)compNode->Component:X}) child count = {childCount} ###{(long)node}"))
|
||||||
{
|
{
|
||||||
if (ImGui.IsItemHovered())
|
if (ImGui.IsItemHovered())
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,9 @@ using System.Numerics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using Dalamud.Configuration.Internal;
|
|
||||||
using Dalamud.Game.Command;
|
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
@ -307,7 +306,7 @@ namespace Dalamud.Interface.Internal.Windows
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.historyPos = -1;
|
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)
|
if (this.history[i] == this.commandText)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using CheapLoc;
|
||||||
using Dalamud.Interface.Colors;
|
using Dalamud.Interface.Colors;
|
||||||
using Dalamud.Interface.Components;
|
using Dalamud.Interface.Components;
|
||||||
using Dalamud.Interface.Windowing;
|
using Dalamud.Interface.Windowing;
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin;
|
using Dalamud.Plugin;
|
||||||
using Dalamud.Plugin.Internal;
|
using Dalamud.Plugin.Internal;
|
||||||
using Dalamud.Plugin.Internal.Exceptions;
|
using Dalamud.Plugin.Internal.Exceptions;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
using ImGuiNET;
|
using ImGuiNET;
|
||||||
using Serilog;
|
|
||||||
|
|
||||||
namespace Dalamud.Interface.Windowing
|
namespace Dalamud.Interface.Windowing
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Dalamud
|
namespace Dalamud.Logging.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Class offering various methods to allow for logging in Dalamud modules.
|
/// Class offering various methods to allow for logging in Dalamud modules.
|
||||||
|
|
@ -3,7 +3,7 @@ using System;
|
||||||
using Serilog.Core;
|
using Serilog.Core;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
|
|
||||||
namespace Dalamud.Interface.Internal
|
namespace Dalamud.Logging.Internal
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Serilog event sink.
|
/// Serilog event sink.
|
||||||
113
Dalamud/Logging/PluginLog.cs
Normal file
113
Dalamud/Logging/PluginLog.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Dalamud.Logging
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class offering various static methods to allow for logging in plugins.
|
||||||
|
/// </summary>
|
||||||
|
public static class PluginLog
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated verbose message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Verbose(string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated verbose message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception that caused the error.</param>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Verbose(Exception exception, string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated debug message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Debug(string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated debug message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception that caused the error.</param>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Debug(Exception exception, string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated information message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Information(string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated information message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception that caused the error.</param>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Information(Exception exception, string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated warning message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Warning(string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated warning message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception that caused the error.</param>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Warning(Exception exception, string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated error message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Error(string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated error message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception that caused the error.</param>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Error(Exception exception, string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated fatal message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Fatal(string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Log a templated fatal message to the in-game debug log.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="exception">The exception that caused the error.</param>
|
||||||
|
/// <param name="messageTemplate">The message template.</param>
|
||||||
|
/// <param name="values">Values to log.</param>
|
||||||
|
public static void Fatal(Exception exception, string messageTemplate, params object[] values)
|
||||||
|
=> Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -347,35 +347,6 @@ namespace Dalamud.Plugin
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Logging
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
[Obsolete("Use PluginLog")]
|
|
||||||
public void Log(string messageTemplate, params object[] values) => Serilog.Log.Information(messageTemplate, values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated error message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
[Obsolete("Use PluginLog")]
|
|
||||||
public void LogError(string messageTemplate, params object[] values) => Serilog.Log.Error(messageTemplate, values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated error message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
[Obsolete("Use PluginLog")]
|
|
||||||
public void LogError(Exception exception, string messageTemplate, params object[] values) => Serilog.Log.Error(exception, messageTemplate, values);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unregister your plugin and dispose all references. You have to call this when your IDalamudPlugin is disposed.
|
/// Unregister your plugin and dispose all references. You have to call this when your IDalamudPlugin is disposed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using Dalamud.Configuration.Internal;
|
using Dalamud.Configuration.Internal;
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
|
|
||||||
namespace Dalamud.Plugin.Internal
|
namespace Dalamud.Plugin.Internal
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
using Dalamud.Configuration.Internal;
|
|
||||||
using Dalamud.Game;
|
using Dalamud.Game;
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Internal.Exceptions;
|
using Dalamud.Plugin.Internal.Exceptions;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using McMaster.NETCore.Plugins;
|
using McMaster.NETCore.Plugins;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ using System.Threading.Tasks;
|
||||||
using CheapLoc;
|
using CheapLoc;
|
||||||
using Dalamud.Configuration;
|
using Dalamud.Configuration;
|
||||||
using Dalamud.Game.Text;
|
using Dalamud.Game.Text;
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Internal.Exceptions;
|
using Dalamud.Plugin.Internal.Exceptions;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Dalamud.Logging.Internal;
|
||||||
using Dalamud.Plugin.Internal.Types;
|
using Dalamud.Plugin.Internal.Types;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,240 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Dalamud.Plugin
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Class offering various static methods to allow for logging in plugins.
|
|
||||||
/// </summary>
|
|
||||||
public static class PluginLog
|
|
||||||
{
|
|
||||||
#region "Log" prefixed Serilog style methods
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Log(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Log(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated verbose message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogVerbose(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated verbose message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogVerbose(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated debug message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogDebug(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated debug message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogDebug(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated information message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogInformation(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated information message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogInformation(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated warning message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogWarning(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated warning message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogWarning(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated error message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogError(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated error message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogError(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated fatal message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void LogFatal(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated fatal message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
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
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated verbose message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Verbose(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated verbose message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Verbose(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated debug message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Debug(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated debug message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Debug(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated information message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Information(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated information message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Information(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated warning message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Warning(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated warning message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Warning(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated error message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Error(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated error message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Error(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated fatal message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Fatal(string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Log a templated fatal message to the in-game debug log.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="exception">The exception that caused the error.</param>
|
|
||||||
/// <param name="messageTemplate">The message template.</param>
|
|
||||||
/// <param name="values">Values to log.</param>
|
|
||||||
public static void Fatal(Exception exception, string messageTemplate, params object[] values)
|
|
||||||
=> Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
|
@ -9,6 +9,6 @@
|
||||||
<NukeScriptDirectory>..</NukeScriptDirectory>
|
<NukeScriptDirectory>..</NukeScriptDirectory>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Nuke.Common" Version="5.1.3" />
|
<PackageReference Include="Nuke.Common" Version="5.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit e3bec118909b0eafdd0ee7c3312c646ce0c3f3dd
|
Subproject commit cbbea8ea911dda876d4a996f214f337e4db88a01
|
||||||
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3724190279a24f638c9627688a837f9b61457668
|
Subproject commit c6ed214c2f7b269c007e5f7f70788745e45e9eb3
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 7fc56bc0a240030d4736e6b16da33b08c73c3ba4
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue