From 48fcebfe12b33adba684e248812b1ba78ce8662e Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Mon, 27 Apr 2020 14:36:00 +0200
Subject: [PATCH 01/21] fix: don't reenable updated plugins automatically
---
Dalamud/Plugin/PluginRepository.cs | 36 +++++++++++++++++++++++-------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/Dalamud/Plugin/PluginRepository.cs b/Dalamud/Plugin/PluginRepository.cs
index 97a80d567..4e68d64cc 100644
--- a/Dalamud/Plugin/PluginRepository.cs
+++ b/Dalamud/Plugin/PluginRepository.cs
@@ -58,14 +58,15 @@ namespace Dalamud.Plugin
}
}
- public bool InstallPlugin(PluginDefinition definition) {
+ public bool InstallPlugin(PluginDefinition definition, bool enableAfterInstall = true) {
try
{
var outputDir = new DirectoryInfo(Path.Combine(this.pluginDirectory, definition.InternalName, definition.AssemblyVersion));
var dllFile = new FileInfo(Path.Combine(outputDir.FullName, $"{definition.InternalName}.dll"));
var disabledFile = new FileInfo(Path.Combine(outputDir.FullName, ".disabled"));
+ var wasDisabled = disabledFile.Exists;
- if (dllFile.Exists)
+ if (dllFile.Exists && enableAfterInstall)
{
if (disabledFile.Exists)
disabledFile.Delete();
@@ -73,9 +74,17 @@ namespace Dalamud.Plugin
return this.manager.LoadPluginFromAssembly(dllFile, false);
}
- if (outputDir.Exists)
- outputDir.Delete(true);
- outputDir.Create();
+ if (dllFile.Exists && !enableAfterInstall) {
+ return true;
+ }
+
+ try {
+ if (outputDir.Exists)
+ outputDir.Delete(true);
+ outputDir.Create();
+ } catch {
+ // ignored, since the plugin may be loaded already
+ }
var path = Path.GetTempFileName();
Log.Information("Downloading plugin to {0}", path);
@@ -86,6 +95,11 @@ namespace Dalamud.Plugin
ZipFile.ExtractToDirectory(path, outputDir.FullName);
+ if (wasDisabled || !enableAfterInstall) {
+ disabledFile.Create();
+ return true;
+ }
+
return this.manager.LoadPluginFromAssembly(dllFile, false);
}
catch (Exception e)
@@ -145,6 +159,12 @@ namespace Dalamud.Plugin
if (!dryRun)
{
+ var wasEnabled =
+ this.manager.Plugins.Where(x => x.Definition != null).Any(
+ x => x.Definition.InternalName == info.InternalName); ;
+
+ Log.Verbose("wasEnabled: {0}", wasEnabled);
+
// Try to disable plugin if it is loaded
try
{
@@ -153,7 +173,7 @@ namespace Dalamud.Plugin
catch (Exception ex)
{
Log.Error(ex, "Plugin disable failed");
- hasError = true;
+ //hasError = true;
}
try {
@@ -165,10 +185,10 @@ namespace Dalamud.Plugin
disabledFile.Create();
}
} catch (Exception ex) {
- Log.Error(ex, "Plugin disable failed");
+ Log.Error(ex, "Plugin disable old versions failed");
}
- var installSuccess = InstallPlugin(remoteInfo);
+ var installSuccess = InstallPlugin(remoteInfo, wasEnabled);
if (installSuccess)
{
From 6e2c55a59cd19b784600dee0c4a46cb812a76f80 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Mon, 27 Apr 2020 14:37:11 +0200
Subject: [PATCH 02/21] build: v4.9.3.0
---
Dalamud.Injector/Dalamud.Injector.csproj | 6 +++---
Dalamud/Dalamud.csproj | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj
index 1ebf766c1..2f5adf457 100644
--- a/Dalamud.Injector/Dalamud.Injector.csproj
+++ b/Dalamud.Injector/Dalamud.Injector.csproj
@@ -14,10 +14,10 @@
true
- 4.9.2.0
- 4.9.2.0
+ 4.9.3.0
+ 4.9.3.0
XIVLauncher addon injection
- 4.9.2.0
+ 4.9.3.0
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index 503a7fbcc..ead306bc1 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -14,9 +14,9 @@
true
- 4.9.2.0
- 4.9.2.0
- 4.9.2.0
+ 4.9.3.0
+ 4.9.3.0
+ 4.9.3.0
From d4244566e81da3e382ce5c172ecd02ddc57e884b Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Mon, 27 Apr 2020 14:51:39 +0200
Subject: [PATCH 03/21] fix: remove asset "version check"
---
Dalamud/Interface/AssetManager.cs | 20 +-------------------
1 file changed, 1 insertion(+), 19 deletions(-)
diff --git a/Dalamud/Interface/AssetManager.cs b/Dalamud/Interface/AssetManager.cs
index a6e19bec8..b2e2311d5 100644
--- a/Dalamud/Interface/AssetManager.cs
+++ b/Dalamud/Interface/AssetManager.cs
@@ -27,17 +27,6 @@ namespace Dalamud.Interface
public static async Task EnsureAssets(string baseDir) {
using var client = new HttpClient();
- var assetVerRemote = await client.GetStringAsync(AssetStoreUrl + "version");
-
- var assetVerPath = Path.Combine(baseDir, "assetver");
- var assetVerLocal = "0";
- if (File.Exists(assetVerPath))
- assetVerLocal = File.ReadAllText(assetVerPath);
-
- var forceRedownload = assetVerLocal != assetVerRemote;
- if (forceRedownload)
- Log.Information("Assets need redownload");
-
Log.Verbose("Starting asset download");
foreach (var entry in AssetDictionary) {
@@ -45,7 +34,7 @@ namespace Dalamud.Interface
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
- if (!File.Exists(filePath) || forceRedownload) {
+ if (!File.Exists(filePath)) {
Log.Verbose("Downloading {0} to {1}...", entry.Key, entry.Value);
try {
File.WriteAllBytes(filePath, await client.GetByteArrayAsync(entry.Key));
@@ -56,13 +45,6 @@ namespace Dalamud.Interface
}
}
-
- try {
- File.WriteAllText(assetVerPath, assetVerRemote);
- } catch (Exception ex) {
- Log.Error(ex, "Could not write asset version.");
- }
}
-
}
}
From bd2e5cda2afff61f7e5625b17dc584a57b844c17 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Mon, 27 Apr 2020 15:17:13 +0200
Subject: [PATCH 04/21] fix: we shouldn't do xivapi requests for characters
when the name is empty
---
Dalamud/DiscordBot/DiscordBotManager.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dalamud/DiscordBot/DiscordBotManager.cs b/Dalamud/DiscordBot/DiscordBotManager.cs
index 4dae26982..6fec653ed 100644
--- a/Dalamud/DiscordBot/DiscordBotManager.cs
+++ b/Dalamud/DiscordBot/DiscordBotManager.cs
@@ -216,7 +216,7 @@ namespace Dalamud.DiscordBot {
var avatarUrl = string.Empty;
var lodestoneId = string.Empty;
- if (!this.config.DisableEmbeds) {
+ if (!this.config.DisableEmbeds && !string.IsNullOrEmpty(senderName)) {
var searchResult = await GetCharacterInfo(senderName, senderWorld);
lodestoneId = searchResult.LodestoneId;
From 017c30e107b84314ff5346f4664f19554e2f58a4 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Tue, 28 Apr 2020 01:48:36 +0200
Subject: [PATCH 05/21] feat: add handler for client send packets
---
Dalamud/Game/Internal/Network/GameNetwork.cs | 97 +++++++++++++++----
.../Network/GameNetworkAddressResolver.cs | 9 +-
.../Network/NetworkMessageDirection.cs | 6 ++
Dalamud/Util.cs | 46 ++++-----
4 files changed, 109 insertions(+), 49 deletions(-)
create mode 100644 Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
diff --git a/Dalamud/Game/Internal/Network/GameNetwork.cs b/Dalamud/Game/Internal/Network/GameNetwork.cs
index eb59ce2a5..384d80315 100644
--- a/Dalamud/Game/Internal/Network/GameNetwork.cs
+++ b/Dalamud/Game/Internal/Network/GameNetwork.cs
@@ -4,55 +4,79 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Dalamud.Hooking;
using Serilog;
+using SharpDX.DXGI;
namespace Dalamud.Game.Internal.Network {
public sealed class GameNetwork : IDisposable {
- [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
- private delegate void ProcessZonePacketDelegate(IntPtr a, IntPtr b, IntPtr dataPtr);
+ #region Hooks
- private readonly Hook processZonePacketHook;
+ [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
+ private delegate void ProcessZonePacketDownDelegate(IntPtr a, IntPtr b, IntPtr dataPtr);
+ private readonly Hook processZonePacketDownHook;
+
+ [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
+ private delegate byte ProcessZonePacketUpDelegate(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4);
+ private readonly Hook processZonePacketUpHook;
+
+ #endregion
private GameNetworkAddressResolver Address { get; }
private IntPtr baseAddress;
public delegate void OnZonePacketDelegate(IntPtr dataPtr);
+ [Obsolete("Please use OnNetworkMessage instead. For modifications, it will take precedence.")]
public OnZonePacketDelegate OnZonePacket;
- private readonly Dalamud dalamud;
+ public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, NetworkMessageDirection direction);
+
+ ///
+ /// Event that is called when a network message is sent/received.
+ ///
+ public OnNetworkMessageDelegate OnNetworkMessage;
+
+
private readonly Queue zoneInjectQueue = new Queue();
- public GameNetwork(Dalamud dalamud, SigScanner scanner) {
- this.dalamud = dalamud;
+ public GameNetwork(SigScanner scanner) {
Address = new GameNetworkAddressResolver();
Address.Setup(scanner);
Log.Verbose("===== G A M E N E T W O R K =====");
- Log.Verbose("ProcessZonePacket address {ProcessZonePacket}", Address.ProcessZonePacket);
+ Log.Verbose("ProcessZonePacketDown address {ProcessZonePacketDown}", Address.ProcessZonePacketDown);
+ Log.Verbose("ProcessZonePacketUp address {ProcessZonePacketUp}", Address.ProcessZonePacketUp);
- this.processZonePacketHook =
- new Hook(Address.ProcessZonePacket,
- new ProcessZonePacketDelegate(ProcessZonePacketDetour),
+ this.processZonePacketDownHook =
+ new Hook(Address.ProcessZonePacketDown,
+ new ProcessZonePacketDownDelegate(ProcessZonePacketDownDetour),
this);
+
+ this.processZonePacketUpHook =
+ new Hook(Address.ProcessZonePacketUp,
+ new ProcessZonePacketUpDelegate(ProcessZonePacketUpDetour),
+ this);
}
public void Enable() {
- this.processZonePacketHook.Enable();
+ this.processZonePacketDownHook.Enable();
+ this.processZonePacketUpHook.Enable();
}
public void Dispose() {
- this.processZonePacketHook.Dispose();
+ this.processZonePacketDownHook.Dispose();
+ this.processZonePacketUpHook.Dispose();
}
- private void ProcessZonePacketDetour(IntPtr a, IntPtr b, IntPtr dataPtr) {
+ private void ProcessZonePacketDownDetour(IntPtr a, IntPtr b, IntPtr dataPtr) {
this.baseAddress = a;
- // Call events
- this.OnZonePacket?.Invoke(dataPtr);
-
try {
- this.processZonePacketHook.Original(a, b, dataPtr);
+ // Call events
+ this.OnZonePacket?.Invoke(dataPtr);
+ this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneDown);
+
+ this.processZonePacketDownHook.Original(a, b, dataPtr);
} catch (Exception ex) {
string header;
try {
@@ -63,12 +87,45 @@ namespace Dalamud.Game.Internal.Network {
header = "failed";
}
- Log.Error(ex, "Exception on ProcessZonePacket hook. Header: " + header);
+ Log.Error(ex, "Exception on ProcessZonePacketDown hook. Header: " + header);
- this.processZonePacketHook.Original(a, b, dataPtr);
+ this.processZonePacketDownHook.Original(a, b, dataPtr);
}
}
+ private byte ProcessZonePacketUpDetour(IntPtr a1, IntPtr dataPtr, IntPtr a3, byte a4) {
+
+ try
+ {
+ // Call events
+ this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneUp);
+
+ var op = Marshal.ReadInt16(dataPtr);
+ var length = Marshal.ReadInt16(dataPtr, 8);
+
+ Log.Verbose("[ZONEUP] op: {0} len: {1}", op.ToString("X"), length);
+ Util.DumpMemory(dataPtr + 0x20, length);
+ }
+ catch (Exception ex)
+ {
+ string header;
+ try
+ {
+ var data = new byte[32];
+ Marshal.Copy(dataPtr, data, 0, 32);
+ header = BitConverter.ToString(data);
+ }
+ catch (Exception)
+ {
+ header = "failed";
+ }
+
+ Log.Error(ex, "Exception on ProcessZonePacketUp hook. Header: " + header);
+ }
+
+ return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4);
+ }
+
#if DEBUG
public void InjectZoneProtoPacket(byte[] data) {
this.zoneInjectQueue.Enqueue(data);
@@ -102,7 +159,7 @@ namespace Dalamud.Game.Internal.Network {
Marshal.Copy(packetData, 0, unmanagedPacketData, packetData.Length);
if (this.baseAddress != IntPtr.Zero) {
- this.processZonePacketHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData);
+ this.processZonePacketDownHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData);
}
Marshal.FreeHGlobal(unmanagedPacketData);
diff --git a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs
index 09ad99ebb..dd78ea2d4 100644
--- a/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs
+++ b/Dalamud/Game/Internal/Network/GameNetworkAddressResolver.cs
@@ -2,12 +2,15 @@ using System;
namespace Dalamud.Game.Internal.Network {
public sealed class GameNetworkAddressResolver : BaseAddressResolver {
- public IntPtr ProcessZonePacket { get; private set; }
-
+ public IntPtr ProcessZonePacketDown { get; private set; }
+ public IntPtr ProcessZonePacketUp { get; private set; }
+
protected override void Setup64Bit(SigScanner sig) {
//ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05");
//ProcessZonePacket = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 73 FF 0F B7 57 02 8D 42 ?? 3D ?? ?? 00 00 0F 87 60 01 00 00 4C 8D 05");
- ProcessZonePacket = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0");
+ ProcessZonePacketDown = sig.ScanText("48 89 74 24 ?? 57 48 83 EC 50 8B FA 49 8B F0");
+ ProcessZonePacketUp =
+ sig.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 56 41 57 48 83 EC 70 8B 81 ?? ?? ?? ??");
}
}
}
diff --git a/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs b/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
new file mode 100644
index 000000000..0074a24de
--- /dev/null
+++ b/Dalamud/Game/Internal/Network/NetworkMessageDirection.cs
@@ -0,0 +1,6 @@
+namespace Dalamud.Game.Internal.Network {
+ public enum NetworkMessageDirection {
+ ZoneDown,
+ ZoneUp
+ }
+}
diff --git a/Dalamud/Util.cs b/Dalamud/Util.cs
index 8c1642c0f..36fbd92b6 100644
--- a/Dalamud/Util.cs
+++ b/Dalamud/Util.cs
@@ -1,19 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
+using Serilog;
-namespace Dalamud
-{
- static class Util
- {
- public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16)
- {
- if (bytes == null)
- {
- return String.Empty;
- }
+namespace Dalamud {
+ internal static class Util {
+ public static void DumpMemory(IntPtr offset, int len = 512) {
+ var data = new byte[len];
+ Marshal.Copy(offset, data, 0, len);
+ Log.Information(ByteArrayToHex(data));
+ }
+
+ public static string ByteArrayToHex(byte[] bytes, int offset = 0, int bytesPerLine = 16) {
+ if (bytes == null) return string.Empty;
var hexChars = "0123456789ABCDEF".ToCharArray();
@@ -26,8 +28,7 @@ namespace Dalamud
var sb = new StringBuilder(numLines * lineLength);
- for (var i = 0; i < bytes.Length; i += bytesPerLine)
- {
+ for (var i = 0; i < bytes.Length; i += bytesPerLine) {
var h = i + offset;
line[0] = hexChars[(h >> 28) & 0xF];
@@ -42,25 +43,18 @@ namespace Dalamud
var hexColumn = offsetBlock;
var charColumn = byteBlock;
- for (var j = 0; j < bytesPerLine; j++)
- {
- if (j > 0 && (j & 7) == 0)
- {
- hexColumn++;
- }
+ for (var j = 0; j < bytesPerLine; j++) {
+ if (j > 0 && (j & 7) == 0) hexColumn++;
- if (i + j >= bytes.Length)
- {
+ if (i + j >= bytes.Length) {
line[hexColumn] = ' ';
line[hexColumn + 1] = ' ';
line[charColumn] = ' ';
- }
- else
- {
+ } else {
var by = bytes[i + j];
- line[hexColumn] = hexChars[(@by >> 4) & 0xF];
- line[hexColumn + 1] = hexChars[@by & 0xF];
- line[charColumn] = @by < 32 ? '.' : (char)@by;
+ line[hexColumn] = hexChars[(by >> 4) & 0xF];
+ line[hexColumn + 1] = hexChars[by & 0xF];
+ line[charColumn] = by < 32 ? '.' : (char) by;
}
hexColumn += 3;
From fd18ba6e8ecb137623cb54ce36cfe8c237589eea Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Tue, 28 Apr 2020 02:33:25 +0200
Subject: [PATCH 06/21] refactor: remove OnZonePacket API
---
Dalamud/Game/Internal/Framework.cs | 2 +-
Dalamud/Game/Internal/Network/GameNetwork.cs | 6 ------
Dalamud/Game/Network/NetworkHandlers.cs | 8 ++++++--
3 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/Dalamud/Game/Internal/Framework.cs b/Dalamud/Game/Internal/Framework.cs
index 78250a17b..e65ead3a0 100644
--- a/Dalamud/Game/Internal/Framework.cs
+++ b/Dalamud/Game/Internal/Framework.cs
@@ -65,7 +65,7 @@ namespace Dalamud.Game.Internal {
Gui = new GameGui(Address.GuiManager, scanner, dalamud);
- Network = new GameNetwork(dalamud, scanner);
+ Network = new GameNetwork(scanner);
//Resource = new ResourceManager(dalamud, scanner);
}
diff --git a/Dalamud/Game/Internal/Network/GameNetwork.cs b/Dalamud/Game/Internal/Network/GameNetwork.cs
index 384d80315..505d7ab73 100644
--- a/Dalamud/Game/Internal/Network/GameNetwork.cs
+++ b/Dalamud/Game/Internal/Network/GameNetwork.cs
@@ -23,11 +23,6 @@ namespace Dalamud.Game.Internal.Network {
private GameNetworkAddressResolver Address { get; }
private IntPtr baseAddress;
- public delegate void OnZonePacketDelegate(IntPtr dataPtr);
-
- [Obsolete("Please use OnNetworkMessage instead. For modifications, it will take precedence.")]
- public OnZonePacketDelegate OnZonePacket;
-
public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, NetworkMessageDirection direction);
///
@@ -73,7 +68,6 @@ namespace Dalamud.Game.Internal.Network {
try {
// Call events
- this.OnZonePacket?.Invoke(dataPtr);
this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneDown);
this.processZonePacketDownHook.Original(a, b, dataPtr);
diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs
index 7f33290c6..f22b8745f 100644
--- a/Dalamud/Game/Network/NetworkHandlers.cs
+++ b/Dalamud/Game/Network/NetworkHandlers.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Dalamud.Data.TransientSheet;
+using Dalamud.Game.Internal.Network;
using Dalamud.Game.Network.MarketBoardUploaders;
using Dalamud.Game.Network.Structures;
using Dalamud.Game.Network.Universalis.MarketBoardUploaders;
@@ -32,11 +33,14 @@ namespace Dalamud.Game.Network {
this.uploader = new UniversalisMarketBoardUploader(dalamud);
- dalamud.Framework.Network.OnZonePacket += OnZonePacket;
+ dalamud.Framework.Network.OnNetworkMessage += OnNetworkMessage;
}
- private void OnZonePacket(IntPtr dataPtr) {
+ private void OnNetworkMessage(IntPtr dataPtr, NetworkMessageDirection direction) {
+ if (direction != NetworkMessageDirection.ZoneDown)
+ return;
+
if (!this.dalamud.Data.IsDataReady)
return;
From 832c5f758fdb16ee6d022204037c8340af4d2d26 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Tue, 28 Apr 2020 17:59:42 +0200
Subject: [PATCH 07/21] fix: only flash window if NOT in foreground
---
Dalamud/Game/Network/NetworkHandlers.cs | 18 ++++++++++--------
Dalamud/NativeFunctions.cs | 23 +++++++++++++++++++++++
2 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs
index f22b8745f..ad723e3c4 100644
--- a/Dalamud/Game/Network/NetworkHandlers.cs
+++ b/Dalamud/Game/Network/NetworkHandlers.cs
@@ -69,14 +69,16 @@ namespace Dalamud.Game.Network {
contentFinderCondition.Image = 112324;
}
- var flashInfo = new NativeFunctions.FLASHWINFO();
- flashInfo.cbSize = (uint) Marshal.SizeOf();
- flashInfo.uCount = uint.MaxValue;
- flashInfo.dwTimeout = 0;
- flashInfo.dwFlags = NativeFunctions.FlashWindow.FLASHW_TRAY |
- NativeFunctions.FlashWindow.FLASHW_TIMERNOFG;
- flashInfo.hwnd = Process.GetCurrentProcess().MainWindowHandle;
- NativeFunctions.FlashWindowEx(ref flashInfo);
+ if (!NativeFunctions.ApplicationIsActivated()) {
+ var flashInfo = new NativeFunctions.FLASHWINFO();
+ flashInfo.cbSize = (uint)Marshal.SizeOf();
+ flashInfo.uCount = uint.MaxValue;
+ flashInfo.dwTimeout = 0;
+ flashInfo.dwFlags = NativeFunctions.FlashWindow.FLASHW_ALL |
+ NativeFunctions.FlashWindow.FLASHW_TIMERNOFG;
+ flashInfo.hwnd = Process.GetCurrentProcess().MainWindowHandle;
+ NativeFunctions.FlashWindowEx(ref flashInfo);
+ }
Task.Run(async () => {
this.dalamud.Framework.Gui.Chat.Print("Duty pop: " + contentFinderCondition.Name);
diff --git a/Dalamud/NativeFunctions.cs b/Dalamud/NativeFunctions.cs
index 1b5f8a5be..37988eb48 100644
--- a/Dalamud/NativeFunctions.cs
+++ b/Dalamud/NativeFunctions.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
@@ -58,6 +59,28 @@ namespace Dalamud
#endregion
+ /// Returns true if the current application has focus, false otherwise
+ public static bool ApplicationIsActivated()
+ {
+ var activatedHandle = GetForegroundWindow();
+ if (activatedHandle == IntPtr.Zero)
+ {
+ return false; // No window is currently activated
+ }
+
+ var procId = Process.GetCurrentProcess().Id;
+ int activeProcId;
+ GetWindowThreadProcessId(activatedHandle, out activeProcId);
+
+ return activeProcId == procId;
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
+ private static extern IntPtr GetForegroundWindow();
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);
+
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FlashWindowEx(ref FLASHWINFO pwfi);
From 10d91031dd53bf207fa68ef62e714f459bdc171c Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Tue, 28 Apr 2020 18:03:37 +0200
Subject: [PATCH 08/21] feat: add ClientOpCodes dict to DataManager
---
Dalamud/Data/DataManager.cs | 21 +++++++++++++++++----
Dalamud/Interface/AssetManager.cs | 1 +
2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/Dalamud/Data/DataManager.cs b/Dalamud/Data/DataManager.cs
index f90f5ea22..090a522c1 100644
--- a/Dalamud/Data/DataManager.cs
+++ b/Dalamud/Data/DataManager.cs
@@ -22,7 +22,14 @@ namespace Dalamud.Data
/// This class provides data for Dalamud-internal features, but can also be used by plugins if needed.
///
public class DataManager {
+ ///
+ /// OpCodes sent by the server to the client.
+ ///
public ReadOnlyDictionary ServerOpCodes { get; private set; }
+ ///
+ /// OpCodes sent by the client to the server.
+ ///
+ public ReadOnlyDictionary ClientOpCodes { get; private set; }
///
/// An object which gives access to any of the game's sheet data.
@@ -55,13 +62,19 @@ namespace Dalamud.Data
{
try
{
- Log.Verbose("Starting data download...");
+ Log.Verbose("Starting data load...");
- var opCodeDict =
+ var zoneOpCodeDict =
JsonConvert.DeserializeObject>(File.ReadAllText(Path.Combine(baseDir, "UIRes", "serveropcode.json")));
- this.ServerOpCodes = new ReadOnlyDictionary(opCodeDict);
+ ServerOpCodes = new ReadOnlyDictionary(zoneOpCodeDict);
- Log.Verbose("Loaded {0} ServerOpCodes.", opCodeDict.Count);
+ Log.Verbose("Loaded {0} ServerOpCodes.", zoneOpCodeDict.Count);
+
+ var clientOpCodeDict =
+ JsonConvert.DeserializeObject>(File.ReadAllText(Path.Combine(baseDir, "UIRes", "clientopcode.json")));
+ ClientOpCodes = new ReadOnlyDictionary(clientOpCodeDict);
+
+ Log.Verbose("Loaded {0} ClientOpCodes.", clientOpCodeDict.Count);
var luminaOptions = new LuminaOptions
diff --git a/Dalamud/Interface/AssetManager.cs b/Dalamud/Interface/AssetManager.cs
index b2e2311d5..2b1d61adf 100644
--- a/Dalamud/Interface/AssetManager.cs
+++ b/Dalamud/Interface/AssetManager.cs
@@ -14,6 +14,7 @@ namespace Dalamud.Interface
private static readonly Dictionary AssetDictionary = new Dictionary {
{AssetStoreUrl + "UIRes/serveropcode.json", "UIRes/serveropcode.json" },
+ {AssetStoreUrl + "UIRes/clientopcode.json", "UIRes/clientopcode.json" },
{AssetStoreUrl + "UIRes/NotoSansCJKjp-Medium.otf", "UIRes/NotoSansCJKjp-Medium.otf" },
{AssetStoreUrl + "UIRes/logo.png", "UIRes/logo.png" },
{AssetStoreUrl + "UIRes/loc/dalamud/dalamud_de.json", "UIRes/loc/dalamud/dalamud_de.json" },
From 193dab20a4901204c316901f7cb40c47eecb4de5 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Tue, 28 Apr 2020 19:50:47 +0200
Subject: [PATCH 09/21] feat: rework network message API again
---
Dalamud/Game/Internal/Network/GameNetwork.cs | 16 +++++++-------
Dalamud/Game/Network/NetworkHandlers.cs | 22 +++++++++-----------
Dalamud/Interface/AssetManager.cs | 1 -
3 files changed, 18 insertions(+), 21 deletions(-)
diff --git a/Dalamud/Game/Internal/Network/GameNetwork.cs b/Dalamud/Game/Internal/Network/GameNetwork.cs
index 505d7ab73..953a775c7 100644
--- a/Dalamud/Game/Internal/Network/GameNetwork.cs
+++ b/Dalamud/Game/Internal/Network/GameNetwork.cs
@@ -11,7 +11,7 @@ namespace Dalamud.Game.Internal.Network {
#region Hooks
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
- private delegate void ProcessZonePacketDownDelegate(IntPtr a, IntPtr b, IntPtr dataPtr);
+ private delegate void ProcessZonePacketDownDelegate(IntPtr a, uint targetId, IntPtr dataPtr);
private readonly Hook processZonePacketDownHook;
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
@@ -23,7 +23,7 @@ namespace Dalamud.Game.Internal.Network {
private GameNetworkAddressResolver Address { get; }
private IntPtr baseAddress;
- public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, NetworkMessageDirection direction);
+ public delegate void OnNetworkMessageDelegate(IntPtr dataPtr, ushort opCode, uint targetId, NetworkMessageDirection direction);
///
/// Event that is called when a network message is sent/received.
@@ -63,14 +63,14 @@ namespace Dalamud.Game.Internal.Network {
this.processZonePacketUpHook.Dispose();
}
- private void ProcessZonePacketDownDetour(IntPtr a, IntPtr b, IntPtr dataPtr) {
+ private void ProcessZonePacketDownDetour(IntPtr a, uint targetId, IntPtr dataPtr) {
this.baseAddress = a;
try {
// Call events
- this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneDown);
+ this.OnNetworkMessage?.Invoke(dataPtr + 0x10, (ushort) Marshal.ReadInt16(dataPtr, 2), targetId, NetworkMessageDirection.ZoneDown);
- this.processZonePacketDownHook.Original(a, b, dataPtr);
+ this.processZonePacketDownHook.Original(a, targetId, dataPtr);
} catch (Exception ex) {
string header;
try {
@@ -83,7 +83,7 @@ namespace Dalamud.Game.Internal.Network {
Log.Error(ex, "Exception on ProcessZonePacketDown hook. Header: " + header);
- this.processZonePacketDownHook.Original(a, b, dataPtr);
+ this.processZonePacketDownHook.Original(a, targetId, dataPtr);
}
}
@@ -92,7 +92,7 @@ namespace Dalamud.Game.Internal.Network {
try
{
// Call events
- this.OnNetworkMessage?.Invoke(dataPtr, NetworkMessageDirection.ZoneUp);
+ this.OnNetworkMessage?.Invoke(dataPtr + 0x20, (ushort) Marshal.ReadInt16(dataPtr), 0x0, NetworkMessageDirection.ZoneUp);
var op = Marshal.ReadInt16(dataPtr);
var length = Marshal.ReadInt16(dataPtr, 8);
@@ -153,7 +153,7 @@ namespace Dalamud.Game.Internal.Network {
Marshal.Copy(packetData, 0, unmanagedPacketData, packetData.Length);
if (this.baseAddress != IntPtr.Zero) {
- this.processZonePacketDownHook.Original(this.baseAddress, IntPtr.Zero, unmanagedPacketData);
+ this.processZonePacketDownHook.Original(this.baseAddress, 0, unmanagedPacketData);
}
Marshal.FreeHGlobal(unmanagedPacketData);
diff --git a/Dalamud/Game/Network/NetworkHandlers.cs b/Dalamud/Game/Network/NetworkHandlers.cs
index ad723e3c4..f0cc9c237 100644
--- a/Dalamud/Game/Network/NetworkHandlers.cs
+++ b/Dalamud/Game/Network/NetworkHandlers.cs
@@ -37,21 +37,19 @@ namespace Dalamud.Game.Network {
}
- private void OnNetworkMessage(IntPtr dataPtr, NetworkMessageDirection direction) {
+ private void OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint targetId, NetworkMessageDirection direction) {
if (direction != NetworkMessageDirection.ZoneDown)
return;
if (!this.dalamud.Data.IsDataReady)
return;
- var opCode = (ushort) Marshal.ReadInt16(dataPtr, 2);
-
if (opCode == this.dalamud.Data.ServerOpCodes["CfNotifyPop"]) {
var data = new byte[64];
Marshal.Copy(dataPtr, data, 0, 64);
- var notifyType = data[16];
- var contentFinderConditionId = BitConverter.ToUInt16(data, 36);
+ var notifyType = data[0];
+ var contentFinderConditionId = BitConverter.ToUInt16(data, 0x14);
if (notifyType != 3)
return;
@@ -103,8 +101,8 @@ namespace Dalamud.Game.Network {
Task.Run(async () => {
for (var rouletteIndex = 1; rouletteIndex < 11; rouletteIndex++) {
- var currentRoleKey = data[16 + rouletteIndex];
- var prevRoleKey = this.lastPreferredRole[16 + rouletteIndex];
+ var currentRoleKey = data[rouletteIndex];
+ var prevRoleKey = this.lastPreferredRole[rouletteIndex];
Log.Verbose("CfPreferredRole: {0} - {1} => {2}", rouletteIndex, prevRoleKey, currentRoleKey);
@@ -145,8 +143,8 @@ namespace Dalamud.Game.Network {
if (!this.optOutMbUploads) {
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) {
- var catalogId = (uint) Marshal.ReadInt32(dataPtr + 0x10);
- var amount = Marshal.ReadByte(dataPtr + 0x1B);
+ var catalogId = (uint) Marshal.ReadInt32(dataPtr);
+ var amount = Marshal.ReadByte(dataPtr + 0xB);
this.marketBoardRequests.Add(new MarketBoardItemRequest {
CatalogId = catalogId,
@@ -160,7 +158,7 @@ namespace Dalamud.Game.Network {
}
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardOfferings"]) {
- var listing = MarketBoardCurrentOfferings.Read(dataPtr + 0x10);
+ var listing = MarketBoardCurrentOfferings.Read(dataPtr);
var request =
this.marketBoardRequests.LastOrDefault(
@@ -215,7 +213,7 @@ namespace Dalamud.Game.Network {
}
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardHistory"]) {
- var listing = MarketBoardHistory.Read(dataPtr + 0x10);
+ var listing = MarketBoardHistory.Read(dataPtr);
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);
@@ -238,7 +236,7 @@ namespace Dalamud.Game.Network {
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
{
- var taxes = MarketTaxRates.Read(dataPtr + 0x10);
+ var taxes = MarketTaxRates.Read(dataPtr);
Log.Verbose("MarketTaxRates: limsa#{0} grid#{1} uldah#{2} ish#{3} kugane#{4} cr#{5}",
taxes.LimsaLominsaTax, taxes.GridaniaTax, taxes.UldahTax, taxes.IshgardTax, taxes.KuganeTax, taxes.CrystariumTax);
diff --git a/Dalamud/Interface/AssetManager.cs b/Dalamud/Interface/AssetManager.cs
index 2b1d61adf..a9aa492e7 100644
--- a/Dalamud/Interface/AssetManager.cs
+++ b/Dalamud/Interface/AssetManager.cs
@@ -43,7 +43,6 @@ namespace Dalamud.Interface
// If another game is running, we don't want to just fail in here
Log.Error(ex, "Could not download asset.");
}
-
}
}
}
From 923dd8b11fd2d2881ffbd36735184200fc77d4f7 Mon Sep 17 00:00:00 2001
From: pmgr <26606291+pmgr@users.noreply.github.com>
Date: Wed, 29 Apr 2020 06:42:11 +0100
Subject: [PATCH 10/21] Added WorldToScreen and a prototype for ScreenToWorld.
---
Dalamud/Game/Internal/Gui/GameGui.cs | 48 +++++++++++++++++++
.../Internal/Gui/GameGuiAddressResolver.cs | 4 ++
2 files changed, 52 insertions(+)
diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs
index 89f64eb2e..764b49d39 100644
--- a/Dalamud/Game/Internal/Gui/GameGui.cs
+++ b/Dalamud/Game/Internal/Gui/GameGui.cs
@@ -3,6 +3,7 @@ using System.Runtime.InteropServices;
using Dalamud.Game.Chat.SeStringHandling.Payloads;
using Dalamud.Hooking;
using Serilog;
+using SharpDX;
namespace Dalamud.Game.Internal.Gui {
public sealed class GameGui : IDisposable {
@@ -34,6 +35,14 @@ namespace Dalamud.Game.Internal.Gui {
private delegate bool OpenMapWithFlagDelegate(IntPtr UIMapObject, string flag);
private OpenMapWithFlagDelegate openMapWithFlag;
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ internal delegate IntPtr GetMatrixSingletonDelegate();
+ internal readonly GetMatrixSingletonDelegate getMatrixSingleton;
+
+ [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
+ private unsafe delegate IntPtr ScreenToWorldNativeDelegate(float *camPosition, float *clipCoords, float rayDistance, float *worldCoords, float *unknown);
+ private readonly ScreenToWorldNativeDelegate screenToWorldNative;
+
///
/// The item ID that is currently hovered by the player. 0 when no item is hovered.
/// If > 1.000.000, subtract 1.000.000 and treat it as HQ
@@ -74,6 +83,12 @@ namespace Dalamud.Game.Internal.Gui {
this);
this.getUIObject = Marshal.GetDelegateForFunctionPointer(Address.GetUIObject);
+
+ this.getMatrixSingleton =
+ Marshal.GetDelegateForFunctionPointer(Address.GetMatrixSingleton);
+
+ this.screenToWorldNative =
+ Marshal.GetDelegateForFunctionPointer(Address.ScreenToWorld);
}
private IntPtr HandleSetGlobalBgmDetour(UInt16 bgmKey, byte a2, UInt32 a3, UInt32 a4, UInt32 a5, byte a6) {
@@ -159,6 +174,39 @@ namespace Dalamud.Game.Internal.Gui {
return this.openMapWithFlag(uiMapObjectPtr, mapLinkString);
}
+ public Vector2 WorldToScreen(Vector3 worldCoords)
+ {
+ // Get base object with matrices
+ var matrixSingleton = this.getMatrixSingleton();
+
+ // Read current ViewProjectionMatrix plus game window size
+ var viewProjectionMatrix = new Matrix();
+ float width, height;
+ unsafe {
+ var rawMatrix = (float*) (matrixSingleton + 0x1b4).ToPointer();
+
+ for (var i = 0; i < 16; i++, rawMatrix += 1) {
+ viewProjectionMatrix[i] = *rawMatrix;
+ }
+
+ width = *rawMatrix;
+ height = *(rawMatrix + 1);
+ }
+
+ Vector3.Transform(ref worldCoords, ref viewProjectionMatrix, out Vector3 pCoords);
+
+ var normalProjCoords = new Vector2(pCoords.X / pCoords.Z, pCoords.Y / pCoords.Z);
+
+ normalProjCoords.X = 0.5f * width * (normalProjCoords.X + 1f);
+ normalProjCoords.Y = 0.5f * height * (1f - normalProjCoords.Y);
+
+ return normalProjCoords;
+ }
+
+ public Vector3 ScreenToWorld(Vector2 screenCoords) {
+ return new Vector3();
+ }
+
public void SetBgm(ushort bgmKey) => this.setGlobalBgmHook.Original(bgmKey, 0, 0, 0, 0, 0);
public void Enable() {
diff --git a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs
index 5142d0d41..0b092fdf6 100644
--- a/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs
+++ b/Dalamud/Game/Internal/Gui/GameGuiAddressResolver.cs
@@ -12,6 +12,8 @@ namespace Dalamud.Game.Internal.Gui {
public IntPtr HandleItemHover { get; set; }
public IntPtr HandleItemOut { get; set; }
public IntPtr GetUIObject { get; private set; }
+ public IntPtr GetMatrixSingleton { get; private set; }
+ public IntPtr ScreenToWorld { get; private set; }
public GameGuiAddressResolver(IntPtr baseAddress) {
BaseAddress = baseAddress;
@@ -31,6 +33,8 @@ namespace Dalamud.Game.Internal.Gui {
HandleItemHover = sig.ScanText("E8 ?? ?? ?? ?? 48 8B 5C 24 ?? 48 89 AE ?? ?? ?? ??");
HandleItemOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 4D");
GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9");
+ GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??");
+ ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1");
}
}
}
From 84d1494b63594e225351757a9da373431681a4be Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Wed, 29 Apr 2020 15:15:41 +0200
Subject: [PATCH 11/21] feat: add implicit conversions to common vector types
to Position3
---
Dalamud/Game/ClientState/Actors/Position3.cs | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/Dalamud/Game/ClientState/Actors/Position3.cs b/Dalamud/Game/ClientState/Actors/Position3.cs
index 381d1a8de..517bc651f 100644
--- a/Dalamud/Game/ClientState/Actors/Position3.cs
+++ b/Dalamud/Game/ClientState/Actors/Position3.cs
@@ -6,5 +6,17 @@ namespace Dalamud.Game.ClientState.Actors {
public float X;
public float Z;
public float Y;
+
+ ///
+ /// Convert this Position3 to a System.Numerics.Vector3
+ ///
+ /// Position to convert.
+ public static implicit operator System.Numerics.Vector3(Position3 pos) => new System.Numerics.Vector3(pos.X, pos.Y, pos.Z);
+
+ ///
+ /// Convert this Position3 to a SharpDX.Vector3
+ ///
+ /// Position to convert.
+ public static implicit operator SharpDX.Vector3(Position3 pos) => new SharpDX.Vector3(pos.X, pos.Y, pos.Z);
}
}
From 8a1c923b369ea6bc5b6e762a19de0f239b2ee2f6 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Wed, 29 Apr 2020 15:34:27 +0200
Subject: [PATCH 12/21] fix: swap X and Z axis for SharpDX vectors
---
Dalamud/Game/ClientState/Actors/Position3.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Dalamud/Game/ClientState/Actors/Position3.cs b/Dalamud/Game/ClientState/Actors/Position3.cs
index 517bc651f..df367a06b 100644
--- a/Dalamud/Game/ClientState/Actors/Position3.cs
+++ b/Dalamud/Game/ClientState/Actors/Position3.cs
@@ -17,6 +17,6 @@ namespace Dalamud.Game.ClientState.Actors {
/// Convert this Position3 to a SharpDX.Vector3
///
/// Position to convert.
- public static implicit operator SharpDX.Vector3(Position3 pos) => new SharpDX.Vector3(pos.X, pos.Y, pos.Z);
+ public static implicit operator SharpDX.Vector3(Position3 pos) => new SharpDX.Vector3(pos.X, pos.Z, pos.Y);
}
}
From 274148361e5a7bc4cc43252d91b0d68adfd8f579 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Wed, 29 Apr 2020 15:34:41 +0200
Subject: [PATCH 13/21] feat: add actor debug overlay for Dalamud Data Window
---
Dalamud/Interface/DalamudDataWindow.cs | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs
index 5232ba3e8..1fac5f67e 100644
--- a/Dalamud/Interface/DalamudDataWindow.cs
+++ b/Dalamud/Interface/DalamudDataWindow.cs
@@ -17,6 +17,8 @@ namespace Dalamud.Interface
private int currentKind;
+ private bool drawActors = false;
+
public DalamudDataWindow(Dalamud dalamud) {
this.dalamud = dalamud;
@@ -84,6 +86,8 @@ namespace Dalamud.Interface
stateString += $"LastLinkedItem: {this.dalamud.Framework.Gui.Chat.LastLinkedItemId.ToString()}\n";
stateString += $"TerritoryType: {this.dalamud.ClientState.TerritoryType}\n\n";
+ ImGui.Checkbox("Draw actors on screen", ref this.drawActors);
+
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
var actor = this.dalamud.ClientState.Actors[i];
@@ -103,6 +107,22 @@ namespace Dalamud.Interface
if (actor is PlayerCharacter pc)
stateString +=
$" HomeWorld: {pc.HomeWorld.GameData.Name} CurrentWorld: {pc.CurrentWorld.GameData.Name} FC: {pc.CompanyTag}\n";
+
+ if (this.drawActors) {
+ var screenCoords = this.dalamud.Framework.Gui.WorldToScreen(actor.Position);
+
+ ImGui.PushID("ActorWindow" + i);
+ ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y));
+ ImGui.SetNextWindowBgAlpha(0.35f);
+ if (ImGui.Begin("Actor" + i,
+ ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.AlwaysAutoResize |
+ ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoMouseInputs |
+ ImGuiWindowFlags.NoFocusOnAppearing | ImGuiWindowFlags.NoNav)) {
+ ImGui.Text($"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name}");
+ ImGui.End();
+ }
+ ImGui.PopID();
+ }
}
}
From 143b8a15fcc0710b479f49e004d04132aac3980d Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Wed, 29 Apr 2020 16:03:58 +0200
Subject: [PATCH 14/21] feat: add plugin authors to credits
---
Dalamud/Dalamud.cs | 8 ++------
Dalamud/Interface/DalamudCreditsWindow.cs | 21 ++++++++++++++++++---
2 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/Dalamud/Dalamud.cs b/Dalamud/Dalamud.cs
index 26fd2b73b..cb35b6fc7 100644
--- a/Dalamud/Dalamud.cs
+++ b/Dalamud/Dalamud.cs
@@ -238,11 +238,7 @@ namespace Dalamud {
this.isImguiDrawDataWindow = true;
}
if (ImGui.MenuItem("Open Credits window")) {
- var logoGraphic =
- this.InterfaceManager.LoadImage(
- Path.Combine(this.StartInfo.WorkingDirectory, "UIRes", "logo.png"));
- this.creditsWindow = new DalamudCreditsWindow(logoGraphic, this.Framework);
- this.isImguiDrawCreditsWindow = true;
+ OnOpenCreditsCommand(null, null);
}
ImGui.MenuItem("Draw ImGui demo", "", ref this.isImguiDrawDemoWindow);
if (ImGui.MenuItem("Dump ImGui info"))
@@ -671,7 +667,7 @@ namespace Dalamud {
var logoGraphic =
this.InterfaceManager.LoadImage(
Path.Combine(this.StartInfo.WorkingDirectory, "UIRes", "logo.png"));
- this.creditsWindow = new DalamudCreditsWindow(logoGraphic, this.Framework);
+ this.creditsWindow = new DalamudCreditsWindow(this, logoGraphic, this.Framework);
this.isImguiDrawCreditsWindow = true;
}
diff --git a/Dalamud/Interface/DalamudCreditsWindow.cs b/Dalamud/Interface/DalamudCreditsWindow.cs
index b2a3fbd2a..153f6fcdb 100644
--- a/Dalamud/Interface/DalamudCreditsWindow.cs
+++ b/Dalamud/Interface/DalamudCreditsWindow.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Numerics;
using Dalamud.Game.Internal;
using ImGuiNET;
@@ -7,10 +8,10 @@ using ImGuiScene;
namespace Dalamud.Interface
{
class DalamudCreditsWindow : IDisposable {
- private string creditsText = @$"
+ private const string CreditsTextTempl = @"
Dalamud
A FFXIV Hooking Framework
-Version {typeof(Dalamud).Assembly.GetName().Version}
+Version {0}
created by:
@@ -44,6 +45,11 @@ gucciBane
+Your plugins were made by:
+
+{1}
+
+
Special thanks:
Adam
@@ -64,14 +70,23 @@ Contribute at: https://github.com/goaaats/Dalamud
Thank you for using XIVLauncher!
";
+ private readonly Dalamud dalamud;
private TextureWrap logoTexture;
private Framework framework;
- public DalamudCreditsWindow(TextureWrap logoTexture, Framework framework) {
+ private string creditsText;
+
+ public DalamudCreditsWindow(Dalamud dalamud, TextureWrap logoTexture, Framework framework) {
+ this.dalamud = dalamud;
this.logoTexture = logoTexture;
this.framework = framework;
framework.Gui.SetBgm(132);
+
+ var pluginCredits = dalamud.PluginManager.Plugins.Where(x => x.Definition != null).Aggregate(string.Empty, (current, plugin) => current + $"{plugin.Definition.Name} by {plugin.Definition.Author}\n");
+
+ this.creditsText =
+ string.Format(CreditsTextTempl, typeof(Dalamud).Assembly.GetName().Version, pluginCredits);
}
public void Dispose() {
From 87bf4980979cc6bd1376415d999e9201840c5744 Mon Sep 17 00:00:00 2001
From: pmgr <26606291+pmgr@users.noreply.github.com>
Date: Wed, 29 Apr 2020 15:39:26 +0100
Subject: [PATCH 15/21] Adding check to WorldToScreen for coordinates being in
front, plus documentation
---
Dalamud/Game/Internal/Gui/GameGui.cs | 23 +++++++++++++++++------
Dalamud/Interface/DalamudDataWindow.cs | 4 +---
2 files changed, 18 insertions(+), 9 deletions(-)
diff --git a/Dalamud/Game/Internal/Gui/GameGui.cs b/Dalamud/Game/Internal/Gui/GameGui.cs
index 764b49d39..aaa800460 100644
--- a/Dalamud/Game/Internal/Gui/GameGui.cs
+++ b/Dalamud/Game/Internal/Gui/GameGui.cs
@@ -141,6 +141,11 @@ namespace Dalamud.Game.Internal.Gui {
return retVal;
}
+ ///
+ /// Opens the in-game map with a flag on the location of the parameter
+ ///
+ /// Link to the map to be opened
+ /// True if there were no errors and it could open the map
public bool OpenMapWithMapLink(MapLinkPayload mapLink)
{
var uiObjectPtr = getUIObject();
@@ -174,7 +179,13 @@ namespace Dalamud.Game.Internal.Gui {
return this.openMapWithFlag(uiMapObjectPtr, mapLinkString);
}
- public Vector2 WorldToScreen(Vector3 worldCoords)
+ ///
+ /// Converts in-world coordinates to screen coordinates (upper left corner origin).
+ ///
+ /// Coordinates in the world
+ /// Converted coordinates
+ /// True if worldPos corresponds to a position in front of the camera
+ public bool WorldToScreen(Vector3 worldPos, out Vector2 screenPos)
{
// Get base object with matrices
var matrixSingleton = this.getMatrixSingleton();
@@ -193,14 +204,14 @@ namespace Dalamud.Game.Internal.Gui {
height = *(rawMatrix + 1);
}
- Vector3.Transform(ref worldCoords, ref viewProjectionMatrix, out Vector3 pCoords);
+ Vector3.Transform( ref worldPos, ref viewProjectionMatrix, out Vector3 pCoords);
- var normalProjCoords = new Vector2(pCoords.X / pCoords.Z, pCoords.Y / pCoords.Z);
+ screenPos = new Vector2(pCoords.X / pCoords.Z, pCoords.Y / pCoords.Z);
- normalProjCoords.X = 0.5f * width * (normalProjCoords.X + 1f);
- normalProjCoords.Y = 0.5f * height * (1f - normalProjCoords.Y);
+ screenPos.X = 0.5f * width * (screenPos.X + 1f);
+ screenPos.Y = 0.5f * height * (1f - screenPos.Y);
- return normalProjCoords;
+ return pCoords.Z > 0;
}
public Vector3 ScreenToWorld(Vector2 screenCoords) {
diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs
index 1fac5f67e..d55476f2b 100644
--- a/Dalamud/Interface/DalamudDataWindow.cs
+++ b/Dalamud/Interface/DalamudDataWindow.cs
@@ -108,9 +108,7 @@ namespace Dalamud.Interface
stateString +=
$" HomeWorld: {pc.HomeWorld.GameData.Name} CurrentWorld: {pc.CurrentWorld.GameData.Name} FC: {pc.CompanyTag}\n";
- if (this.drawActors) {
- var screenCoords = this.dalamud.Framework.Gui.WorldToScreen(actor.Position);
-
+ if (this.drawActors && this.dalamud.Framework.Gui.WorldToScreen(actor.Position, out var screenCoords)) {
ImGui.PushID("ActorWindow" + i);
ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y));
ImGui.SetNextWindowBgAlpha(0.35f);
From 0800cc4e916c9b7c92f48cd9793ec0bcb5843579 Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Wed, 29 Apr 2020 18:56:21 +0200
Subject: [PATCH 16/21] feat: add draw distance to actor view
---
Dalamud/Game/ClientState/Actors/Types/Actor.cs | 10 ++++++++++
Dalamud/Game/ClientState/Structs/Actor.cs | 4 ++--
Dalamud/Interface/DalamudDataWindow.cs | 11 +++++++++--
3 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/Dalamud/Game/ClientState/Actors/Types/Actor.cs b/Dalamud/Game/ClientState/Actors/Types/Actor.cs
index 275a5cd39..2289a8b30 100644
--- a/Dalamud/Game/ClientState/Actors/Types/Actor.cs
+++ b/Dalamud/Game/ClientState/Actors/Types/Actor.cs
@@ -49,5 +49,15 @@ namespace Dalamud.Game.ClientState.Actors.Types {
/// possible values.
///
public ObjectKind ObjectKind => this.actorStruct.ObjectKind;
+
+ ///
+ /// The X distance from the local player in yalms.
+ ///
+ public byte YalmDistanceX => this.actorStruct.YalmDistanceFromPlayerX;
+
+ ///
+ /// The Y distance from the local player in yalms.
+ ///
+ public byte YalmDistanceY => this.actorStruct.YalmDistanceFromPlayerY;
}
}
diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs
index 68090891b..934ba630f 100644
--- a/Dalamud/Game/ClientState/Structs/Actor.cs
+++ b/Dalamud/Game/ClientState/Structs/Actor.cs
@@ -20,9 +20,9 @@ namespace Dalamud.Game.ClientState.Structs
[FieldOffset(140)] public ObjectKind ObjectKind;
[FieldOffset(141)] public byte SubKind;
[FieldOffset(142)] public bool IsFriendly;
- [FieldOffset(144)] public byte YalmDistanceFromPlayer1; // Demo says one of these is x distance
+ [FieldOffset(144)] public byte YalmDistanceFromPlayerX; // Demo says one of these is x distance
[FieldOffset(145)] public byte PlayerTargetStatus; // This is some kind of enum
- [FieldOffset(146)] public byte YalmDistanceFromPlayer2; // and the other is z distance
+ [FieldOffset(146)] public byte YalmDistanceFromPlayerY; // and the other is z distance
[FieldOffset(160)] public Position3 Position;
[FieldOffset(0x17F8)] public int TargetActorId;
// This field can't be correctly aligned, so we have to cut it manually.
diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs
index d55476f2b..59284f113 100644
--- a/Dalamud/Interface/DalamudDataWindow.cs
+++ b/Dalamud/Interface/DalamudDataWindow.cs
@@ -1,3 +1,4 @@
+using System;
using System.Linq;
using System.Numerics;
using Dalamud.Game.Chat;
@@ -18,6 +19,7 @@ namespace Dalamud.Interface
private int currentKind;
private bool drawActors = false;
+ private float maxActorDrawDistance = 20;
public DalamudDataWindow(Dalamud dalamud) {
this.dalamud = dalamud;
@@ -87,6 +89,7 @@ namespace Dalamud.Interface
stateString += $"TerritoryType: {this.dalamud.ClientState.TerritoryType}\n\n";
ImGui.Checkbox("Draw actors on screen", ref this.drawActors);
+ ImGui.SliderFloat("Draw Distance", ref this.maxActorDrawDistance, 2f, 40f);
for (var i = 0; i < this.dalamud.ClientState.Actors.Length; i++) {
var actor = this.dalamud.ClientState.Actors[i];
@@ -95,7 +98,7 @@ namespace Dalamud.Interface
continue;
stateString +=
- $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - {actor.Position.X} {actor.Position.Y} {actor.Position.Z}\n";
+ $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX}\n";
if (actor is Npc npc)
stateString += $" DataId: {npc.DataId} NameId:{npc.NameId}\n";
@@ -111,7 +114,11 @@ namespace Dalamud.Interface
if (this.drawActors && this.dalamud.Framework.Gui.WorldToScreen(actor.Position, out var screenCoords)) {
ImGui.PushID("ActorWindow" + i);
ImGui.SetNextWindowPos(new Vector2(screenCoords.X, screenCoords.Y));
- ImGui.SetNextWindowBgAlpha(0.35f);
+
+ if (actor.YalmDistanceX > this.maxActorDrawDistance)
+ continue;
+
+ ImGui.SetNextWindowBgAlpha(Math.Max(1f - (actor.YalmDistanceX / this.maxActorDrawDistance), 0.2f));
if (ImGui.Begin("Actor" + i,
ImGuiWindowFlags.NoDecoration | ImGuiWindowFlags.AlwaysAutoResize |
ImGuiWindowFlags.NoSavedSettings | ImGuiWindowFlags.NoMove | ImGuiWindowFlags.NoMouseInputs |
From fcd98ee2bb557c8048c91749e03b8defed593b32 Mon Sep 17 00:00:00 2001
From: meli <57847713+ff-meli@users.noreply.github.com>
Date: Wed, 29 Apr 2020 17:13:05 -0700
Subject: [PATCH 17/21] Add ability for plugins to add ImGui fonts at runtime,
though we should discourage this as much as possible. Also sneak in an
api-matching update to part of ImGuiScene, to make more things useable in
SamplePlugin
---
Dalamud/Interface/InterfaceManager.cs | 85 +++++++++++++++++++--------
Dalamud/Interface/UiBuilder.cs | 20 +++++++
lib/ImGuiScene | 2 +-
3 files changed, 81 insertions(+), 26 deletions(-)
diff --git a/Dalamud/Interface/InterfaceManager.cs b/Dalamud/Interface/InterfaceManager.cs
index 3d66d24d8..5fde5a051 100644
--- a/Dalamud/Interface/InterfaceManager.cs
+++ b/Dalamud/Interface/InterfaceManager.cs
@@ -54,11 +54,15 @@ namespace Dalamud.Interface
public ImGuiIOPtr LastImGuiIoPtr;
+ public Action OnBuildFonts;
+ private bool isRebuildingFonts = false;
+
///
/// This event gets called by a plugin UiBuilder when read
///
public event RawDX11Scene.BuildUIDelegate OnDraw;
+
public InterfaceManager(Dalamud dalamud, SigScanner scanner)
{
this.dalamud = dalamud;
@@ -200,7 +204,18 @@ namespace Dalamud.Interface
return null;
}
- private unsafe IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
+ // Sets up a deferred invocation of font rebuilding, before the next render frame
+ public void RebuildFonts()
+ {
+ // don't invoke this multiple times per frame, in case multiple plugins call it
+ if (!this.isRebuildingFonts)
+ {
+ this.isRebuildingFonts = true;
+ this.scene.OnNewRenderFrame += RebuildFontsInternal;
+ }
+ }
+
+ private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)
{
if (this.scene == null)
{
@@ -209,30 +224,7 @@ namespace Dalamud.Interface
this.scene.OnBuildUI += Display;
this.scene.OnNewInputFrame += OnNewInputFrame;
- ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
- fontConfig.MergeMode = true;
- fontConfig.PixelSnapH = true;
-
- var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
- ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
-
- var fontPathGame = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "gamesym.ttf");
- Log.Verbose(fontPathGame);
-
- var rangeHandle = GCHandle.Alloc(new ushort[]
- {
- 0xE020,
- 0xE0DB,
- 0
- }, GCHandleType.Pinned);
-
-
- ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, rangeHandle.AddrOfPinnedObject());
-
- ImGui.GetIO().Fonts.Build();
-
- fontConfig.Destroy();
- rangeHandle.Free();
+ SetupFonts();
ImGui.GetStyle().GrabRounding = 3f;
ImGui.GetStyle().FrameRounding = 4f;
@@ -268,6 +260,49 @@ namespace Dalamud.Interface
return this.presentHook.Original(swapChain, syncInterval, presentFlags);
}
+ private unsafe void SetupFonts()
+ {
+ ImGui.GetIO().Fonts.Clear();
+
+ ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
+ fontConfig.MergeMode = true;
+ fontConfig.PixelSnapH = true;
+
+ var fontPathJp = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "NotoSansCJKjp-Medium.otf");
+ ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathJp, 17.0f, null, ImGui.GetIO().Fonts.GetGlyphRangesJapanese());
+
+ var fontPathGame = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "UIRes", "gamesym.ttf");
+ Log.Verbose(fontPathGame);
+
+ var rangeHandle = GCHandle.Alloc(new ushort[]
+ {
+ 0xE020,
+ 0xE0DB,
+ 0
+ }, GCHandleType.Pinned);
+
+
+ ImGui.GetIO().Fonts.AddFontFromFileTTF(fontPathGame, 17.0f, fontConfig, rangeHandle.AddrOfPinnedObject());
+
+ OnBuildFonts?.Invoke();
+
+ ImGui.GetIO().Fonts.Build();
+
+ fontConfig.Destroy();
+ rangeHandle.Free();
+ }
+
+ // This is intended to only be called as a handler attached to scene.OnNewRenderFrame
+ private void RebuildFontsInternal()
+ {
+ SetupFonts();
+
+ this.scene.OnNewRenderFrame -= RebuildFontsInternal;
+ this.scene.InvalidateFonts();
+
+ this.isRebuildingFonts = false;
+ }
+
private IntPtr ResizeBuffersDetour(IntPtr swapChain, uint bufferCount, uint width, uint height, uint newFormat, uint swapChainFlags)
{
Log.Verbose($"Calling resizebuffers {bufferCount} {width} {height} {newFormat} {swapChainFlags}");
diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs
index 31468e302..8b2d3f30a 100644
--- a/Dalamud/Interface/UiBuilder.cs
+++ b/Dalamud/Interface/UiBuilder.cs
@@ -70,6 +70,26 @@ namespace Dalamud.Interface
public TextureWrap LoadImageRaw(byte[] imageData, int width, int height, int numChannels) =>
this.interfaceManager.LoadImageRaw(imageData, width, height, numChannels);
+ ///
+ /// An event that is called any time ImGui fonts need to be rebuilt.
+ /// Any ImFontPtr objects that you store can be invalidated when fonts are rebuilt
+ /// (at any time), so you should both reload your custom fonts and restore those
+ /// pointers inside this handler.
+ ///
+ public Action OnBuildFonts
+ {
+ get { return this.interfaceManager.OnBuildFonts; }
+ set { this.interfaceManager.OnBuildFonts = value; }
+ }
+
+ ///
+ /// Call this to queue a rebuild of the font atlas.
+ /// This will invoke any handlers and ensure that any loaded fonts are
+ /// ready to be used on the next UI frame.
+ ///
+ public void RebuildFonts() =>
+ this.interfaceManager.RebuildFonts();
+
///
/// Event that is fired when the plugin should open its configuration interface.
///
diff --git a/lib/ImGuiScene b/lib/ImGuiScene
index aaa037938..d5b9345dc 160000
--- a/lib/ImGuiScene
+++ b/lib/ImGuiScene
@@ -1 +1 @@
-Subproject commit aaa037938d6fe835a15542a3451d12108e3f83b6
+Subproject commit d5b9345dc1463d746b832843bd7c81b753d4e5b0
From de3b771d34b6133ceeaf17a100ccb6709fad6758 Mon Sep 17 00:00:00 2001
From: meli <57847713+ff-meli@users.noreply.github.com>
Date: Wed, 29 Apr 2020 17:17:22 -0700
Subject: [PATCH 18/21] whine at people in api comments
---
Dalamud/Interface/UiBuilder.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Dalamud/Interface/UiBuilder.cs b/Dalamud/Interface/UiBuilder.cs
index 8b2d3f30a..9728d1270 100644
--- a/Dalamud/Interface/UiBuilder.cs
+++ b/Dalamud/Interface/UiBuilder.cs
@@ -74,7 +74,8 @@ namespace Dalamud.Interface
/// An event that is called any time ImGui fonts need to be rebuilt.
/// Any ImFontPtr objects that you store can be invalidated when fonts are rebuilt
/// (at any time), so you should both reload your custom fonts and restore those
- /// pointers inside this handler.
+ /// pointers inside this handler.
+ /// PLEASE remove this handler inside Dipose, or when you no longer need your fonts!
///
public Action OnBuildFonts
{
From 520cd4bddc5cd1d334f31941be2d35d9b007eb7e Mon Sep 17 00:00:00 2001
From: goat <16760685+goaaats@users.noreply.github.com>
Date: Thu, 30 Apr 2020 14:10:02 +0200
Subject: [PATCH 19/21] feat: add Customize to Chara
---
Dalamud.Injector/Dalamud.Injector.csproj | 83 +++++-----
Dalamud/Dalamud.csproj | 148 +++++++++---------
.../Game/ClientState/Actors/CustomizeIndex.cs | 41 +++++
.../Game/ClientState/Actors/Types/Chara.cs | 5 +
Dalamud/Game/ClientState/Structs/Actor.cs | 12 +-
Dalamud/Interface/DalamudDataWindow.cs | 2 +-
6 files changed, 172 insertions(+), 119 deletions(-)
create mode 100644 Dalamud/Game/ClientState/Actors/CustomizeIndex.cs
diff --git a/Dalamud.Injector/Dalamud.Injector.csproj b/Dalamud.Injector/Dalamud.Injector.csproj
index 2f5adf457..cf79dd174 100644
--- a/Dalamud.Injector/Dalamud.Injector.csproj
+++ b/Dalamud.Injector/Dalamud.Injector.csproj
@@ -1,41 +1,46 @@
-
- AnyCPU
- net48
- 8.0
- AnyCPU;x64
-
-
- Exe
- $(SolutionDir)/bin
- false
- true
- Portable
-
-
- true
- 4.9.3.0
- 4.9.3.0
- XIVLauncher addon injection
- 4.9.3.0
-
-
-
-
-
- false
-
-
- dalamud.ico
-
-
-
-
-
-
-
-
-
-
-
+
+ AnyCPU
+ net48
+ 8.0
+ AnyCPU;x64
+
+
+ Exe
+ $(SolutionDir)/bin
+ false
+ true
+ Portable
+
+
+ true
+ 4.9.3.0
+ 4.9.3.0
+ XIVLauncher addon injection
+ 4.9.3.0
+
+
+
+
+
+ $(MSBuildProjectDirectory)\
+ $(AppOutputBase)=C:\goatsoft\companysecrets\injector\
+ true
+
+
+ false
+
+
+ dalamud.ico
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Dalamud/Dalamud.csproj b/Dalamud/Dalamud.csproj
index ead306bc1..e8fd28ddf 100644
--- a/Dalamud/Dalamud.csproj
+++ b/Dalamud/Dalamud.csproj
@@ -1,79 +1,73 @@
-
- AnyCPU
- net472
- 8.0
- AnyCPU;x64
-
-
- Library
-
- false
- true
- Portable
-
-
- true
- 4.9.3.0
- 4.9.3.0
- 4.9.3.0
-
-
-
-
-
- $(SolutionDir)\bin\Dalamud.xml
-
-
- $(SolutionDir)\bin\Dalamud.xml
-
-
- $(SolutionDir)\bin\Dalamud.xml
-
-
- $(SolutionDir)bin\Dalamud.xml
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- Resources.resx
-
-
-
-
- ResXFileCodeGenerator
- Resources.Designer.cs
-
-
-
-
-
-
-
-
-
+
+ AnyCPU
+ net472
+ 8.0
+ AnyCPU;x64
+
+
+ Library
+
+ false
+ true
+ Portable
+ $(SolutionDir)\bin\Dalamud.xml
+
+
+ true
+ 4.9.3.0
+ 4.9.3.0
+ 4.9.3.0
+
+
+
+
+
+ $(MSBuildProjectDirectory)\
+ $(AppOutputBase)=C:\goatsoft\companysecrets\dalamud\
+ true
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
diff --git a/Dalamud/Game/ClientState/Actors/CustomizeIndex.cs b/Dalamud/Game/ClientState/Actors/CustomizeIndex.cs
new file mode 100644
index 000000000..93553f0b7
--- /dev/null
+++ b/Dalamud/Game/ClientState/Actors/CustomizeIndex.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Dalamud.Game.ClientState.Actors
+{
+ ///
+ /// This enum describes the indices of the Customize array.
+ ///
+ // TODO: This may need some rework since it may not be entirely accurate (stolen from Sapphire)
+ public enum CustomizeIndex {
+ Race = 0x00,
+ Gender = 0x01,
+ Tribe = 0x04,
+ Height = 0x03,
+ ModelType = 0x02, // Au Ra: changes horns/tails, everything else: seems to drastically change appearance (flip between two sets, odd/even numbers). sometimes retains hairstyle and other features
+ FaceType = 0x05,
+ HairStyle = 0x06,
+ HasHighlights = 0x07, // negative to enable, positive to disable
+ SkinColor = 0x08,
+ EyeColor = 0x09, // color of character's right eye
+ HairColor = 0x0A, // main color
+ HairColor2 = 0x0B, // highlights color
+ FaceFeatures = 0x0C, // seems to be a toggle, (-odd and +even for large face covering), opposite for small
+ FaceFeaturesColor = 0x0D,
+ Eyebrows = 0x0E,
+ EyeColor2 = 0x0F, // color of character's left eye
+ EyeShape = 0x10,
+ NoseShape = 0x11,
+ JawShape = 0x12,
+ LipStyle = 0x13, // lip colour depth and shape (negative values around -120 darker/more noticeable, positive no colour)
+ LipColor = 0x14,
+ RaceFeatureSize = 0x15,
+ RaceFeatureType = 0x16, // negative or out of range tail shapes for race result in no tail (e.g. Au Ra has max of 4 tail shapes), incorrect value can crash client
+ BustSize = 0x17, // char creator allows up to max of 100, i set to 127 cause who wouldnt but no visible difference
+ Facepaint = 0x18,
+ FacepaintColor = 0x19,
+ }
+}
diff --git a/Dalamud/Game/ClientState/Actors/Types/Chara.cs b/Dalamud/Game/ClientState/Actors/Types/Chara.cs
index 45471e719..06b0657f9 100644
--- a/Dalamud/Game/ClientState/Actors/Types/Chara.cs
+++ b/Dalamud/Game/ClientState/Actors/Types/Chara.cs
@@ -43,5 +43,10 @@ namespace Dalamud.Game.ClientState.Actors.Types {
/// The maximum MP of this Chara.
///
public int MaxMp => this.actorStruct.MaxMp;
+
+ ///
+ /// Byte array describing the visual appearance of this Chara. Indexed by .
+ ///
+ public byte[] Customize => this.actorStruct.Customize;
}
}
diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs
index 934ba630f..89308a2f2 100644
--- a/Dalamud/Game/ClientState/Structs/Actor.cs
+++ b/Dalamud/Game/ClientState/Structs/Actor.cs
@@ -13,7 +13,9 @@ namespace Dalamud.Game.ClientState.Structs
///
[StructLayout(LayoutKind.Explicit)]
public struct Actor {
- [FieldOffset(0x30)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)] public string Name;
+ [FieldOffset(0x30)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
+ public string Name;
+
[FieldOffset(116)] public int ActorId;
[FieldOffset(128)] public int DataId;
[FieldOffset(132)] public int OwnerId;
@@ -24,9 +26,15 @@ namespace Dalamud.Game.ClientState.Structs
[FieldOffset(145)] public byte PlayerTargetStatus; // This is some kind of enum
[FieldOffset(146)] public byte YalmDistanceFromPlayerY; // and the other is z distance
[FieldOffset(160)] public Position3 Position;
+
+ [FieldOffset(0x17B8)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize;
+
[FieldOffset(0x17F8)] public int TargetActorId;
+
// This field can't be correctly aligned, so we have to cut it manually.
- [FieldOffset(0x17d0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)] public byte[] CompanyTag;
+ [FieldOffset(0x17d0)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 7)]
+ public byte[] CompanyTag;
+
[FieldOffset(0x1868)] public int NameId;
[FieldOffset(0x1884)] public byte CurrentWorld;
[FieldOffset(0x1886)] public byte HomeWorld;
diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs
index 59284f113..8b8828676 100644
--- a/Dalamud/Interface/DalamudDataWindow.cs
+++ b/Dalamud/Interface/DalamudDataWindow.cs
@@ -105,7 +105,7 @@ namespace Dalamud.Interface
if (actor is Chara chara)
stateString +=
- $" Level: {chara.Level} ClassJob: {chara.ClassJob.GameData.Name} CHP: {chara.CurrentHp} MHP: {chara.MaxHp} CMP: {chara.CurrentMp} MMP: {chara.MaxMp}\n";
+ $" Level: {chara.Level} ClassJob: {chara.ClassJob.GameData.Name} CHP: {chara.CurrentHp} MHP: {chara.MaxHp} CMP: {chara.CurrentMp} MMP: {chara.MaxMp}\n Customize: {BitConverter.ToString(chara.Customize).Replace("-", " ")}\n";
if (actor is PlayerCharacter pc)
stateString +=
From f1b51708b406ad46b2a6262be135c16266ac5d28 Mon Sep 17 00:00:00 2001
From: meli <57847713+ff-meli@users.noreply.github.com>
Date: Thu, 30 Apr 2020 16:50:34 -0700
Subject: [PATCH 20/21] Update ActorTable offsets for hp/mp, add ui
(display-only.. probably) status effects
---
Dalamud/Game/ClientState/Actors/Types/Chara.cs | 2 +-
Dalamud/Game/ClientState/Structs/Actor.cs | 12 ++++++++----
.../Game/ClientState/Structs/StatusEffect.cs | 18 ++++++++++++++++++
3 files changed, 27 insertions(+), 5 deletions(-)
create mode 100644 Dalamud/Game/ClientState/Structs/StatusEffect.cs
diff --git a/Dalamud/Game/ClientState/Actors/Types/Chara.cs b/Dalamud/Game/ClientState/Actors/Types/Chara.cs
index 06b0657f9..467ad087a 100644
--- a/Dalamud/Game/ClientState/Actors/Types/Chara.cs
+++ b/Dalamud/Game/ClientState/Actors/Types/Chara.cs
@@ -42,7 +42,7 @@ namespace Dalamud.Game.ClientState.Actors.Types {
///
/// The maximum MP of this Chara.
///
- public int MaxMp => this.actorStruct.MaxMp;
+ public int MaxMp => 10000; // Currently hardcoded because the value in actorStruct is very questionable.
///
/// Byte array describing the visual appearance of this Chara. Indexed by .
diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs
index 89308a2f2..745eb7e76 100644
--- a/Dalamud/Game/ClientState/Structs/Actor.cs
+++ b/Dalamud/Game/ClientState/Structs/Actor.cs
@@ -38,12 +38,16 @@ namespace Dalamud.Game.ClientState.Structs
[FieldOffset(0x1868)] public int NameId;
[FieldOffset(0x1884)] public byte CurrentWorld;
[FieldOffset(0x1886)] public byte HomeWorld;
- [FieldOffset(6328)] public int CurrentHp;
- [FieldOffset(6332)] public int MaxHp;
- [FieldOffset(6336)] public int CurrentMp;
- [FieldOffset(6340)] public int MaxMp;
+ [FieldOffset(0x1898)] public int CurrentHp;
+ [FieldOffset(0x189C)] public int MaxHp;
+ [FieldOffset(0x18A0)] public int CurrentMp;
+ // This value is weird. It seems to change semi-randomly between 0 and 10k, definitely
+ // in response to mp-using events, but it doesn't often have a value and the changing seems
+ // somewhat arbitrary.
+ [FieldOffset(0x18AA)] public int MaxMp;
[FieldOffset(6358)] public byte ClassJob;
[FieldOffset(6360)] public byte Level;
+ [FieldOffset(0x1958)][MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] public StatusEffect[] UIStatusEffects;
}
}
diff --git a/Dalamud/Game/ClientState/Structs/StatusEffect.cs b/Dalamud/Game/ClientState/Structs/StatusEffect.cs
new file mode 100644
index 000000000..584c5c48d
--- /dev/null
+++ b/Dalamud/Game/ClientState/Structs/StatusEffect.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace Dalamud.Game.ClientState.Structs
+{
+ ///
+ /// Native memory representation of a FFXIV status effect.
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StatusEffect
+ {
+ public short EffectId;
+ public byte StackCount;
+ public byte Param;
+ public float Duration;
+ public int OwnerId;
+ }
+}
From 2e39dd07e334f0bba71c4194bbb88d9b394bf183 Mon Sep 17 00:00:00 2001
From: meli <57847713+ff-meli@users.noreply.github.com>
Date: Thu, 30 Apr 2020 18:34:42 -0700
Subject: [PATCH 21/21] Add actor rotation
---
Dalamud/Game/ClientState/Actors/Types/Actor.cs | 6 ++++++
Dalamud/Game/ClientState/Structs/Actor.cs | 1 +
Dalamud/Interface/DalamudDataWindow.cs | 2 +-
3 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Dalamud/Game/ClientState/Actors/Types/Actor.cs b/Dalamud/Game/ClientState/Actors/Types/Actor.cs
index 2289a8b30..caed4962d 100644
--- a/Dalamud/Game/ClientState/Actors/Types/Actor.cs
+++ b/Dalamud/Game/ClientState/Actors/Types/Actor.cs
@@ -34,6 +34,12 @@ namespace Dalamud.Game.ClientState.Actors.Types {
///
public Position3 Position => this.actorStruct.Position;
+ ///
+ /// Rotation of this .
+ /// This ranges from -pi to pi radians.
+ ///
+ public float Rotation => this.actorStruct.Rotation;
+
///
/// Displayname of this Actor.
///
diff --git a/Dalamud/Game/ClientState/Structs/Actor.cs b/Dalamud/Game/ClientState/Structs/Actor.cs
index 745eb7e76..b8cf25680 100644
--- a/Dalamud/Game/ClientState/Structs/Actor.cs
+++ b/Dalamud/Game/ClientState/Structs/Actor.cs
@@ -26,6 +26,7 @@ namespace Dalamud.Game.ClientState.Structs
[FieldOffset(145)] public byte PlayerTargetStatus; // This is some kind of enum
[FieldOffset(146)] public byte YalmDistanceFromPlayerY; // and the other is z distance
[FieldOffset(160)] public Position3 Position;
+ [FieldOffset(176)] public float Rotation; // Rotation around the vertical axis (yaw), from -pi to pi radians
[FieldOffset(0x17B8)] [MarshalAs(UnmanagedType.ByValArray, SizeConst = 28)] public byte[] Customize;
diff --git a/Dalamud/Interface/DalamudDataWindow.cs b/Dalamud/Interface/DalamudDataWindow.cs
index 8b8828676..aefbe4e0b 100644
--- a/Dalamud/Interface/DalamudDataWindow.cs
+++ b/Dalamud/Interface/DalamudDataWindow.cs
@@ -98,7 +98,7 @@ namespace Dalamud.Interface
continue;
stateString +=
- $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX}\n";
+ $"{actor.Address.ToInt64():X}:{actor.ActorId:X}[{i}] - {actor.ObjectKind} - {actor.Name} - X{actor.Position.X} Y{actor.Position.Y} Z{actor.Position.Z} D{actor.YalmDistanceX} R{actor.Rotation}\n";
if (actor is Npc npc)
stateString += $" DataId: {npc.DataId} NameId:{npc.NameId}\n";