Merge pull request #477 from daemitus/misc

This commit is contained in:
goaaats 2021-08-19 16:59:46 +02:00 committed by GitHub
commit 8d5d290656
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 279 additions and 324 deletions

View file

@ -64,6 +64,21 @@ dotnet_style_predefined_type_for_member_access = true:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_parentheses_in_other_operators=always_for_clarity:silent dotnet_style_parentheses_in_other_operators=always_for_clarity:silent
dotnet_style_object_initializer = false dotnet_style_object_initializer = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_empty_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_before_open_square_brackets = false
csharp_space_before_comma = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_comma = true
csharp_space_after_cast = false
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = none
csharp_space_between_square_brackets = false
# ReSharper properties # ReSharper properties
resharper_align_linq_query = true resharper_align_linq_query = true

View file

@ -61,8 +61,6 @@ namespace Dalamud.Injector
var process = GetProcess(args.ElementAtOrDefault(1)); var process = GetProcess(args.ElementAtOrDefault(1));
var startInfo = GetStartInfo(args.ElementAtOrDefault(2), process); var startInfo = GetStartInfo(args.ElementAtOrDefault(2), process);
startInfo.WorkingDirectory = Directory.GetCurrentDirectory();
// This seems to help with the STATUS_INTERNAL_ERROR condition // This seems to help with the STATUS_INTERNAL_ERROR condition
Thread.Sleep(1000); Thread.Sleep(1000);
@ -245,7 +243,7 @@ namespace Dalamud.Injector
startInfo = new DalamudStartInfo startInfo = new DalamudStartInfo
{ {
WorkingDirectory = null, WorkingDirectory = Directory.GetCurrentDirectory(),
ConfigurationPath = Path.Combine(xivlauncherDir, "dalamudConfig.json"), ConfigurationPath = Path.Combine(xivlauncherDir, "dalamudConfig.json"),
PluginDirectory = Path.Combine(xivlauncherDir, "installedPlugins"), PluginDirectory = Path.Combine(xivlauncherDir, "installedPlugins"),
DefaultPluginDirectory = Path.Combine(xivlauncherDir, "devPlugins"), DefaultPluginDirectory = Path.Combine(xivlauncherDir, "devPlugins"),

View file

@ -35,9 +35,7 @@ namespace Dalamud
#region Internals #region Internals
private readonly ManualResetEvent unloadSignal; private readonly ManualResetEvent unloadSignal;
private readonly ManualResetEvent finishUnloadSignal; private readonly ManualResetEvent finishUnloadSignal;
private bool hasDisposedPlugins = false; private bool hasDisposedPlugins = false;
#endregion #endregion
@ -237,6 +235,7 @@ namespace Dalamud
// Initialize FFXIVClientStructs function resolver // Initialize FFXIVClientStructs function resolver
FFXIVClientStructs.Resolver.Initialize(); FFXIVClientStructs.Resolver.Initialize();
Log.Information("[T1] FFXIVClientStructs initialized!"); Log.Information("[T1] FFXIVClientStructs initialized!");
} }
catch (Exception ex) catch (Exception ex)

View file

@ -9,47 +9,47 @@ namespace Dalamud
/// Struct containing information needed to initialize Dalamud. /// Struct containing information needed to initialize Dalamud.
/// </summary> /// </summary>
[Serializable] [Serializable]
public struct DalamudStartInfo public record DalamudStartInfo
{ {
/// <summary> /// <summary>
/// The working directory of the XIVLauncher installations. /// Gets the working directory of the XIVLauncher installations.
/// </summary> /// </summary>
public string WorkingDirectory; public string WorkingDirectory { get; init; }
/// <summary> /// <summary>
/// The path to the configuration file. /// Gets the path to the configuration file.
/// </summary> /// </summary>
public string ConfigurationPath; public string ConfigurationPath { get; init; }
/// <summary> /// <summary>
/// The path to the directory for installed plugins. /// Gets the path to the directory for installed plugins.
/// </summary> /// </summary>
public string PluginDirectory; public string PluginDirectory { get; init; }
/// <summary> /// <summary>
/// The path to the directory for developer plugins. /// Gets the path to the directory for developer plugins.
/// </summary> /// </summary>
public string DefaultPluginDirectory; public string DefaultPluginDirectory { get; init; }
/// <summary> /// <summary>
/// The path to core Dalamud assets. /// Gets the path to core Dalamud assets.
/// </summary> /// </summary>
public string AssetDirectory; public string AssetDirectory { get; init; }
/// <summary> /// <summary>
/// The language of the game client. /// Gets the language of the game client.
/// </summary> /// </summary>
public ClientLanguage Language; public ClientLanguage Language { get; init; }
/// <summary> /// <summary>
/// The current game version code. /// Gets the current game version code.
/// </summary> /// </summary>
[JsonConverter(typeof(GameVersionConverter))] [JsonConverter(typeof(GameVersionConverter))]
public GameVersion GameVersion; public GameVersion GameVersion { get; init; }
/// <summary> /// <summary>
/// Whether or not market board information should be uploaded by default. /// Gets a value indicating whether or not market board information should be uploaded by default.
/// </summary> /// </summary>
public bool OptOutMbCollection; public bool OptOutMbCollection { get; init; }
} }
} }

View file

@ -31,21 +31,14 @@ namespace Dalamud.Game.Command
{ {
this.dalamud = dalamud; this.dalamud = dalamud;
switch (language) this.currentLangCommandRegex = language switch
{ {
case ClientLanguage.Japanese: ClientLanguage.Japanese => this.commandRegexJp,
this.currentLangCommandRegex = this.commandRegexJp; ClientLanguage.English => this.commandRegexEn,
break; ClientLanguage.German => this.commandRegexDe,
case ClientLanguage.English: ClientLanguage.French => this.commandRegexFr,
this.currentLangCommandRegex = this.commandRegexEn; _ => this.currentLangCommandRegex,
break; };
case ClientLanguage.German:
this.currentLangCommandRegex = this.commandRegexDe;
break;
case ClientLanguage.French:
this.currentLangCommandRegex = this.commandRegexFr;
break;
}
dalamud.Framework.Gui.Chat.CheckMessageHandled += this.OnCheckMessageHandled; dalamud.Framework.Gui.Chat.CheckMessageHandled += this.OnCheckMessageHandled;
} }

View file

@ -1,63 +0,0 @@
using System;
using Dalamud.Memory;
namespace Dalamud.Game.Gui.Addons
{
/// <summary>
/// This class represents an in-game UI "Addon".
/// </summary>
public unsafe class Addon
{
/// <summary>
/// Initializes a new instance of the <see cref="Addon"/> class.
/// </summary>
/// <param name="address">The address of the addon.</param>
public Addon(IntPtr address)
{
this.Address = address;
}
/// <summary>
/// Gets the address of the addon.
/// </summary>
public IntPtr Address { get; }
/// <summary>
/// Gets the name of the addon.
/// </summary>
public string Name => MemoryHelper.ReadString((IntPtr)this.Struct->Name, 0x20);
/// <summary>
/// Gets the X position of the addon on screen.
/// </summary>
public short X => this.Struct->X;
/// <summary>
/// Gets the Y position of the addon on screen.
/// </summary>
public short Y => this.Struct->Y;
/// <summary>
/// Gets the scale of the addon.
/// </summary>
public float Scale => this.Struct->Scale;
/// <summary>
/// Gets the width of the addon. This may include non-visible parts.
/// </summary>
public unsafe float Width => this.Struct->RootNode->Width * this.Scale;
/// <summary>
/// Gets the height of the addon. This may include non-visible parts.
/// </summary>
public unsafe float Height => this.Struct->RootNode->Height * this.Scale;
/// <summary>
/// Gets a value indicating whether the addon is visible.
/// </summary>
public bool Visible => this.Struct->IsVisible;
private FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase* Struct => (FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*)this.Address;
}
}

View file

@ -70,7 +70,7 @@ namespace Dalamud.Game.Gui.FlyText
/// </summary> /// </summary>
private delegate IntPtr CreateFlyTextDelegate( private delegate IntPtr CreateFlyTextDelegate(
IntPtr addonFlyText, IntPtr addonFlyText,
int kind, FlyTextKind kind,
int val1, int val1,
int val2, int val2,
IntPtr text2, IntPtr text2,
@ -126,14 +126,14 @@ namespace Dalamud.Game.Gui.FlyText
public unsafe void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon) public unsafe void AddFlyText(FlyTextKind kind, uint actorIndex, uint val1, uint val2, SeString text1, SeString text2, uint color, uint icon)
{ {
// Known valid flytext region within the atk arrays // Known valid flytext region within the atk arrays
int numIndex = 28; var numIndex = 28;
int strIndex = 25; var strIndex = 25;
uint numOffset = 147; var numOffset = 147u;
uint strOffset = 28; var strOffset = 28u;
// Get the UI module and flytext addon pointers // Get the UI module and flytext addon pointers
var ui = (UIModule*)this.Dalamud.Framework.Gui.GetUIModule(); var ui = (UIModule*)this.Dalamud.Framework.Gui.GetUIModule();
var flytext = this.Dalamud.Framework.Gui.GetUiObjectByName("_FlyText", 1); var flytext = this.Dalamud.Framework.Gui.GetAddonByName("_FlyText", 1);
if (ui == null || flytext == IntPtr.Zero) if (ui == null || flytext == IntPtr.Zero)
return; return;
@ -195,7 +195,7 @@ namespace Dalamud.Game.Gui.FlyText
private IntPtr CreateFlyTextDetour( private IntPtr CreateFlyTextDetour(
IntPtr addonFlyText, IntPtr addonFlyText,
int kind, FlyTextKind kind,
int val1, int val1,
int val2, int val2,
IntPtr text2, IntPtr text2,
@ -211,7 +211,7 @@ namespace Dalamud.Game.Gui.FlyText
var handled = false; var handled = false;
var tmpKind = (FlyTextKind)kind; var tmpKind = kind;
var tmpVal1 = val1; var tmpVal1 = val1;
var tmpVal2 = val2; var tmpVal2 = val2;
var tmpText1 = MemoryHelper.ReadSeStringNullTerminated(text1); var tmpText1 = MemoryHelper.ReadSeStringNullTerminated(text1);
@ -224,7 +224,7 @@ namespace Dalamud.Game.Gui.FlyText
var cmpText2 = tmpText2.ToString(); var cmpText2 = tmpText2.ToString();
Log.Verbose($"[FlyText] Called with addonFlyText({addonFlyText.ToInt64():X}) " + Log.Verbose($"[FlyText] Called with addonFlyText({addonFlyText.ToInt64():X}) " +
$"kind({((FlyTextKind)kind).ToString()}) val1({val1}) val2({val2}) " + $"kind({kind}) val1({val1}) val2({val2}) " +
$"text1({text1.ToInt64():X}, \"{tmpText1}\") text2({text2.ToInt64():X}, \"{tmpText2}\") " + $"text1({text1.ToInt64():X}, \"{tmpText1}\") text2({text2.ToInt64():X}, \"{tmpText2}\") " +
$"color({color:X}) icon({icon}) yOffset({yOffset})"); $"color({color:X}) icon({icon}) yOffset({yOffset})");
Log.Verbose("[FlyText] Calling flytext events!"); Log.Verbose("[FlyText] Calling flytext events!");
@ -250,14 +250,14 @@ namespace Dalamud.Game.Gui.FlyText
} }
// Check if any values have changed // Check if any values have changed
var dirty = tmpKind != (FlyTextKind)kind || var dirty = tmpKind != kind ||
tmpVal1 != val1 || tmpVal1 != val1 ||
tmpVal2 != val2 || tmpVal2 != val2 ||
tmpText1.ToString() != cmpText1 || tmpText1.ToString() != cmpText1 ||
tmpText2.ToString() != cmpText2 || tmpText2.ToString() != cmpText2 ||
tmpColor != color || tmpColor != color ||
tmpIcon != icon || tmpIcon != icon ||
Math.Abs(tmpYOffset - yOffset) > float.Epsilon; Math.Abs(tmpYOffset - yOffset) > float.Epsilon;
// If not dirty, make the original call // If not dirty, make the original call
if (!dirty) if (!dirty)
@ -276,7 +276,7 @@ namespace Dalamud.Game.Gui.FlyText
retVal = this.createFlyTextHook.Original( retVal = this.createFlyTextHook.Original(
addonFlyText, addonFlyText,
(int)tmpKind, tmpKind,
tmpVal1, tmpVal1,
tmpVal2, tmpVal2,
pText2, pText2,

View file

@ -4,7 +4,7 @@ namespace Dalamud.Game.Gui.FlyText
/// Enum of FlyTextKind values. Members suffixed with /// Enum of FlyTextKind values. Members suffixed with
/// a number seem to be a duplicate, or perform duplicate behavior. /// a number seem to be a duplicate, or perform duplicate behavior.
/// </summary> /// </summary>
public enum FlyTextKind public enum FlyTextKind : int
{ {
/// <summary> /// <summary>
/// Val1 in serif font, Text2 in sans-serif as subtitle. /// Val1 in serif font, Text2 in sans-serif as subtitle.
@ -19,8 +19,8 @@ namespace Dalamud.Game.Gui.FlyText
DirectHit = 1, DirectHit = 1,
/// <summary> /// <summary>
/// Val1 in larger serif font with exclamation, with Text2 /// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle.
/// in sans-serif as subtitle. Does a bigger bounce effect on appearance. /// Does a bigger bounce effect on appearance.
/// </summary> /// </summary>
CriticalHit = 2, CriticalHit = 2,
@ -75,6 +75,10 @@ namespace Dalamud.Game.Gui.FlyText
/// Icon next to sans-serif Text1. /// Icon next to sans-serif Text1.
/// </summary> /// </summary>
NamedIcon = 12, NamedIcon = 12,
/// <summary>
/// Icon next to sans-serif Text1 (2).
/// </summary>
NamedIcon2 = 13, NamedIcon2 = 13,
/// <summary> /// <summary>
@ -92,8 +96,19 @@ namespace Dalamud.Game.Gui.FlyText
/// </summary> /// </summary>
NamedTp = 16, NamedTp = 16,
/// <summary>
/// AutoAttack with sans-serif Text1 to the left of the Val1 (2).
/// </summary>
NamedAttack2 = 17, NamedAttack2 = 17,
/// <summary>
/// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle (2).
/// </summary>
NamedMp2 = 18, NamedMp2 = 18,
/// <summary>
/// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle (2).
/// </summary>
NamedTp2 = 19, NamedTp2 = 19,
/// <summary> /// <summary>
@ -122,9 +137,25 @@ namespace Dalamud.Game.Gui.FlyText
/// AutoAttack with no Text2. /// AutoAttack with no Text2.
/// </summary> /// </summary>
AutoAttackNoText = 24, AutoAttackNoText = 24,
/// <summary>
/// AutoAttack with no Text2 (2).
/// </summary>
AutoAttackNoText2 = 25, AutoAttackNoText2 = 25,
/// <summary>
/// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle. Does a bigger bounce effect on appearance (2).
/// </summary>
CriticalHit2 = 26, CriticalHit2 = 26,
/// <summary>
/// AutoAttack with no Text2 (3).
/// </summary>
AutoAttackNoText3 = 27, AutoAttackNoText3 = 27,
/// <summary>
/// CriticalHit with sans-serif Text1 to the left of the Val1 (2).
/// </summary>
NamedCriticalHit2 = 28, NamedCriticalHit2 = 28,
/// <summary> /// <summary>
@ -148,6 +179,11 @@ namespace Dalamud.Game.Gui.FlyText
/// Same as NamedIcon but Text1 is slightly faded. Used for buff expiration. /// Same as NamedIcon but Text1 is slightly faded. Used for buff expiration.
/// </summary> /// </summary>
NamedIconFaded = 32, NamedIconFaded = 32,
/// <summary>
/// Same as NamedIcon but Text1 is slightly faded (2).
/// Used for buff expiration.
/// </summary>
NamedIconFaded2 = 33, NamedIconFaded2 = 33,
/// <summary> /// <summary>
@ -175,8 +211,19 @@ namespace Dalamud.Game.Gui.FlyText
/// </summary> /// </summary>
NamedHasNoEffect = 38, NamedHasNoEffect = 38,
/// <summary>
/// AutoAttack with sans-serif Text1 to the left of the Val1 (3).
/// </summary>
NamedAttack3 = 39, NamedAttack3 = 39,
/// <summary>
/// Sans-serif Text1 next to serif Val1 with all caps condensed font MP with Text2 in sans-serif as subtitle (3).
/// </summary>
NamedMp3 = 40, NamedMp3 = 40,
/// <summary>
/// Sans-serif Text1 next to serif Val1 with all caps condensed font TP with Text2 in sans-serif as subtitle (3).
/// </summary>
NamedTp3 = 41, NamedTp3 = 41,
/// <summary> /// <summary>
@ -194,7 +241,15 @@ namespace Dalamud.Game.Gui.FlyText
/// </summary> /// </summary>
NamedIconWithItemOutline = 44, NamedIconWithItemOutline = 44,
/// <summary>
/// AutoAttack with no Text2 (4).
/// </summary>
AutoAttackNoText4 = 45, AutoAttackNoText4 = 45,
/// <summary>
/// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle (3).
/// Does a bigger bounce effect on appearance.
/// </summary>
CriticalHit3 = 46, CriticalHit3 = 46,
/// <summary> /// <summary>
@ -207,8 +262,22 @@ namespace Dalamud.Game.Gui.FlyText
/// </summary> /// </summary>
Reflected = 48, Reflected = 48,
/// <summary>
/// Val1 in serif font, Text2 in sans-serif as subtitle (2).
/// Does a bounce effect on appearance.
/// </summary>
DirectHit2 = 49, DirectHit2 = 49,
CriticalHit5 = 50,
/// <summary>
/// Val1 in larger serif font with exclamation, with Text2 in sans-serif as subtitle (4).
/// Does a bigger bounce effect on appearance.
/// </summary>
CriticalHit4 = 50,
/// <summary>
/// Val1 in even larger serif font with 2 exclamations, Text2 in sans-serif as subtitle (2).
/// Does a large bounce effect on appearance. Does not scroll up or down the screen.
/// </summary>
CriticalDirectHit2 = 51, CriticalDirectHit2 = 51,
} }
} }

View file

@ -2,9 +2,9 @@ using System;
using System.Numerics; using System.Numerics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Dalamud.Game.Gui.Addons;
using Dalamud.Game.Gui.FlyText; using Dalamud.Game.Gui.FlyText;
using Dalamud.Game.Gui.PartyFinder; using Dalamud.Game.Gui.PartyFinder;
using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Interface; using Dalamud.Interface;
@ -23,10 +23,7 @@ namespace Dalamud.Game.Gui
private readonly GameGuiAddressResolver address; private readonly GameGuiAddressResolver address;
private readonly GetMatrixSingletonDelegate getMatrixSingleton; private readonly GetMatrixSingletonDelegate getMatrixSingleton;
private readonly GetUIObjectDelegate getUIObject;
private readonly ScreenToWorldNativeDelegate screenToWorldNative; private readonly ScreenToWorldNativeDelegate screenToWorldNative;
private readonly GetUIObjectByNameDelegate getUIObjectByName;
private readonly GetUiModuleDelegate getUiModule;
private readonly GetAgentModuleDelegate getAgentModule; private readonly GetAgentModuleDelegate getAgentModule;
private readonly Hook<SetGlobalBgmDelegate> setGlobalBgmHook; private readonly Hook<SetGlobalBgmDelegate> setGlobalBgmHook;
@ -61,7 +58,6 @@ namespace Dalamud.Game.Gui
Log.Verbose($"HandleItemHover address 0x{this.address.HandleItemHover.ToInt64():X}"); Log.Verbose($"HandleItemHover address 0x{this.address.HandleItemHover.ToInt64():X}");
Log.Verbose($"HandleItemOut address 0x{this.address.HandleItemOut.ToInt64():X}"); Log.Verbose($"HandleItemOut address 0x{this.address.HandleItemOut.ToInt64():X}");
Log.Verbose($"HandleImm address 0x{this.address.HandleImm.ToInt64():X}"); Log.Verbose($"HandleImm address 0x{this.address.HandleImm.ToInt64():X}");
Log.Verbose($"GetUIObject address 0x{this.address.GetUIObject.ToInt64():X}");
Log.Verbose($"GetAgentModule address 0x{this.address.GetAgentModule.ToInt64():X}"); Log.Verbose($"GetAgentModule address 0x{this.address.GetAgentModule.ToInt64():X}");
this.Chat = new ChatGui(this.address.ChatManager, scanner, dalamud); this.Chat = new ChatGui(this.address.ChatManager, scanner, dalamud);
@ -79,44 +75,23 @@ namespace Dalamud.Game.Gui
this.handleImmHook = new Hook<HandleImmDelegate>(this.address.HandleImm, this.HandleImmDetour); this.handleImmHook = new Hook<HandleImmDelegate>(this.address.HandleImm, this.HandleImmDetour);
this.getUIObject = Marshal.GetDelegateForFunctionPointer<GetUIObjectDelegate>(this.address.GetUIObject);
this.getMatrixSingleton = Marshal.GetDelegateForFunctionPointer<GetMatrixSingletonDelegate>(this.address.GetMatrixSingleton); this.getMatrixSingleton = Marshal.GetDelegateForFunctionPointer<GetMatrixSingletonDelegate>(this.address.GetMatrixSingleton);
this.screenToWorldNative = Marshal.GetDelegateForFunctionPointer<ScreenToWorldNativeDelegate>(this.address.ScreenToWorld); this.screenToWorldNative = Marshal.GetDelegateForFunctionPointer<ScreenToWorldNativeDelegate>(this.address.ScreenToWorld);
this.toggleUiHideHook = new Hook<ToggleUiHideDelegate>(this.address.ToggleUiHide, this.ToggleUiHideDetour); this.toggleUiHideHook = new Hook<ToggleUiHideDelegate>(this.address.ToggleUiHide, this.ToggleUiHideDetour);
this.GetBaseUIObject = Marshal.GetDelegateForFunctionPointer<GetBaseUIObjectDelegate>(this.address.GetBaseUIObject);
this.getUIObjectByName = Marshal.GetDelegateForFunctionPointer<GetUIObjectByNameDelegate>(this.address.GetUIObjectByName);
this.getUiModule = Marshal.GetDelegateForFunctionPointer<GetUiModuleDelegate>(this.address.GetUIModule);
this.getAgentModule = Marshal.GetDelegateForFunctionPointer<GetAgentModuleDelegate>(this.address.GetAgentModule); this.getAgentModule = Marshal.GetDelegateForFunctionPointer<GetAgentModuleDelegate>(this.address.GetAgentModule);
} }
// Marshaled delegates // Marshaled delegates
/// <summary>
/// The delegate type of the native method that gets the Client::UI::UIModule address.
/// </summary>
/// <returns>The Client::UI::UIModule address.</returns>
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr GetBaseUIObjectDelegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr GetMatrixSingletonDelegate(); private delegate IntPtr GetMatrixSingletonDelegate();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr GetUIObjectDelegate();
[UnmanagedFunctionPointer(CallingConvention.ThisCall)] [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private unsafe delegate bool ScreenToWorldNativeDelegate(float* camPos, float* clipPos, float rayDistance, float* worldPos, int* unknown); private unsafe delegate bool ScreenToWorldNativeDelegate(float* camPos, float* clipPos, float rayDistance, float* worldPos, int* unknown);
[UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Ansi)]
private delegate IntPtr GetUIObjectByNameDelegate(IntPtr thisPtr, string uiName, int index);
private delegate IntPtr GetUiModuleDelegate(IntPtr basePtr);
private delegate IntPtr GetAgentModuleDelegate(IntPtr uiModule); private delegate IntPtr GetAgentModuleDelegate(IntPtr uiModule);
// Hooked delegates // Hooked delegates
@ -153,12 +128,6 @@ namespace Dalamud.Game.Gui
/// </summary> /// </summary>
public event EventHandler<bool> OnUiHideToggled; public event EventHandler<bool> OnUiHideToggled;
/// <summary>
/// Gets a callable delegate for the GetBaseUIObject game method.
/// </summary>
/// <returns>The Client::UI::UIModule address.</returns>
public GetBaseUIObjectDelegate GetBaseUIObject { get; }
/// <summary> /// <summary>
/// Gets the <see cref="Chat"/> instance. /// Gets the <see cref="Chat"/> instance.
/// </summary> /// </summary>
@ -212,19 +181,19 @@ namespace Dalamud.Game.Gui
/// <returns>True if there were no errors and it could open the map.</returns> /// <returns>True if there were no errors and it could open the map.</returns>
public bool OpenMapWithMapLink(MapLinkPayload mapLink) public bool OpenMapWithMapLink(MapLinkPayload mapLink)
{ {
var uiObjectPtr = this.getUIObject(); var uiModule = this.GetUIModule();
if (uiObjectPtr.Equals(IntPtr.Zero)) if (uiModule == IntPtr.Zero)
{ {
Log.Error("OpenMapWithMapLink: Null pointer returned from getUIObject()"); Log.Error("OpenMapWithMapLink: Null pointer returned from getUIObject()");
return false; return false;
} }
this.getUIMapObject = this.address.GetVirtualFunction<GetUIMapObjectDelegate>(uiObjectPtr, 0, 8); this.getUIMapObject = this.address.GetVirtualFunction<GetUIMapObjectDelegate>(uiModule, 0, 8);
var uiMapObjectPtr = this.getUIMapObject(uiObjectPtr); var uiMapObjectPtr = this.getUIMapObject(uiModule);
if (uiMapObjectPtr.Equals(IntPtr.Zero)) if (uiMapObjectPtr == IntPtr.Zero)
{ {
Log.Error("OpenMapWithMapLink: Null pointer returned from GetUIMapObject()"); Log.Error("OpenMapWithMapLink: Null pointer returned from GetUIMapObject()");
return false; return false;
@ -407,37 +376,40 @@ namespace Dalamud.Game.Gui
/// Gets a pointer to the game's UI module. /// Gets a pointer to the game's UI module.
/// </summary> /// </summary>
/// <returns>IntPtr pointing to UI module.</returns> /// <returns>IntPtr pointing to UI module.</returns>
public IntPtr GetUIModule() => this.getUiModule(this.dalamud.Framework.Address.BaseAddress); public unsafe IntPtr GetUIModule()
/// <summary>
/// Gets the pointer to the UI Object with the given name and index.
/// </summary>
/// <param name="name">Name of UI to find.</param>
/// <param name="index">Index of UI to find (1-indexed).</param>
/// <returns>IntPtr.Zero if unable to find UI, otherwise IntPtr pointing to the start of the UI Object.</returns>
public IntPtr GetUiObjectByName(string name, int index)
{ {
var baseUi = this.GetBaseUIObject(); var framework = FFXIVClientStructs.FFXIV.Client.System.Framework.Framework.Instance();
if (baseUi == IntPtr.Zero) return IntPtr.Zero; if (framework == null)
var baseUiProperties = Marshal.ReadIntPtr(baseUi, 0x20); return IntPtr.Zero;
if (baseUiProperties == IntPtr.Zero) return IntPtr.Zero;
return this.getUIObjectByName(baseUiProperties, name, index); var uiModule = framework->GetUiModule();
if (uiModule == null)
return IntPtr.Zero;
return (IntPtr)uiModule;
} }
/// <summary> /// <summary>
/// Gets an Addon by it's internal name. /// Gets the pointer to the Addon with the given name and index.
/// </summary> /// </summary>
/// <param name="name">The addon name.</param> /// <param name="name">Name of addon to find.</param>
/// <param name="index">The index of the addon, starting at 1.</param> /// <param name="index">Index of addon to find (1-indexed).</param>
/// <returns>The native memory representation of the addon, if it exists.</returns> /// <returns>IntPtr.Zero if unable to find UI, otherwise IntPtr pointing to the start of the addon.</returns>
public Addon GetAddonByName(string name, int index) public unsafe IntPtr GetAddonByName(string name, int index)
{ {
var address = this.GetUiObjectByName(name, index); var atkStage = FFXIVClientStructs.FFXIV.Component.GUI.AtkStage.GetSingleton();
if (atkStage == null)
return IntPtr.Zero;
if (address == IntPtr.Zero) var unitMgr = atkStage->RaptureAtkUnitManager;
return null; if (unitMgr == null)
return IntPtr.Zero;
return new Addon(address); var addon = unitMgr->GetAddonByName(name, index);
if (addon == null)
return IntPtr.Zero;
return (IntPtr)addon;
} }
/// <summary> /// <summary>
@ -447,7 +419,7 @@ namespace Dalamud.Game.Gui
/// <returns>A pointer to the agent interface.</returns> /// <returns>A pointer to the agent interface.</returns>
public IntPtr FindAgentInterface(string addonName) public IntPtr FindAgentInterface(string addonName)
{ {
var addon = this.dalamud.Framework.Gui.GetUiObjectByName(addonName, 1); var addon = this.GetAddonByName(addonName, 1);
return this.FindAgentInterface(addon); return this.FindAgentInterface(addon);
} }
@ -456,7 +428,14 @@ namespace Dalamud.Game.Gui
/// </summary> /// </summary>
/// <param name="addon">The addon address.</param> /// <param name="addon">The addon address.</param>
/// <returns>A pointer to the agent interface.</returns> /// <returns>A pointer to the agent interface.</returns>
public IntPtr FindAgentInterface(IntPtr addon) public unsafe IntPtr FindAgentInterface(void* addon) => this.FindAgentInterface((IntPtr)addon);
/// <summary>
/// Find the agent associated with an addon, if possible.
/// </summary>
/// <param name="addon">The addon address.</param>
/// <returns>A pointer to the agent interface.</returns>
public unsafe IntPtr FindAgentInterface(IntPtr addon)
{ {
if (addon == IntPtr.Zero) if (addon == IntPtr.Zero)
return IntPtr.Zero; return IntPtr.Zero;
@ -473,9 +452,10 @@ namespace Dalamud.Game.Gui
return IntPtr.Zero; return IntPtr.Zero;
} }
var id = Marshal.ReadInt16(addon, 0x1CE); var unitBase = (FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*)addon;
var id = unitBase->ParentID;
if (id == 0) if (id == 0)
id = Marshal.ReadInt16(addon, 0x1CC); id = unitBase->ID;
if (id == 0) if (id == 0)
return IntPtr.Zero; return IntPtr.Zero;

View file

@ -57,11 +57,6 @@ namespace Dalamud.Game.Gui
/// </summary> /// </summary>
public IntPtr HandleImm { get; private set; } public IntPtr HandleImm { get; private set; }
/// <summary>
/// Gets the address of the native GetUIObject method.
/// </summary>
public IntPtr GetUIObject { get; private set; }
/// <summary> /// <summary>
/// Gets the address of the native GetMatrixSingleton method. /// Gets the address of the native GetMatrixSingleton method.
/// </summary> /// </summary>
@ -77,21 +72,6 @@ namespace Dalamud.Game.Gui
/// </summary> /// </summary>
public IntPtr ToggleUiHide { get; private set; } public IntPtr ToggleUiHide { get; private set; }
/// <summary>
/// Gets the address of the native Client::UI::UIModule getter method.
/// </summary>
public IntPtr GetBaseUIObject { get; private set; }
/// <summary>
/// Gets the address of the native GetUIObjectByName method.
/// </summary>
public IntPtr GetUIObjectByName { get; private set; }
/// <summary>
/// Gets the address of the native GetUIModule method.
/// </summary>
public IntPtr GetUIModule { get; private set; }
/// <summary> /// <summary>
/// Gets the address of the native GetAgentModule method. /// Gets the address of the native GetAgentModule method.
/// </summary> /// </summary>
@ -106,13 +86,9 @@ namespace Dalamud.Game.Gui
this.HandleActionHover = sig.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 83 F8 0F"); this.HandleActionHover = sig.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 83 F8 0F");
this.HandleActionOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B DA 48 8B F9 4D 85 C0 74 1F"); this.HandleActionOut = sig.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B DA 48 8B F9 4D 85 C0 74 1F");
this.HandleImm = sig.ScanText("E8 ?? ?? ?? ?? 84 C0 75 10 48 83 FF 09"); this.HandleImm = sig.ScanText("E8 ?? ?? ?? ?? 84 C0 75 10 48 83 FF 09");
this.GetUIObject = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 8B 10 FF 52 40 80 88 ?? ?? ?? ?? 01 E9");
this.GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??"); this.GetMatrixSingleton = sig.ScanText("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? 48 89 4c 24 ?? 4C 8D 4D ?? 4C 8D 44 24 ??");
this.ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1"); this.ScreenToWorld = sig.ScanText("48 83 EC 48 48 8B 05 ?? ?? ?? ?? 4D 8B D1");
this.ToggleUiHide = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 0F B6 B9 ?? ?? ?? ?? B8 ?? ?? ?? ??"); this.ToggleUiHide = sig.ScanText("48 89 5C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 0F B6 B9 ?? ?? ?? ?? B8 ?? ?? ?? ??");
this.GetBaseUIObject = sig.ScanText("E8 ?? ?? ?? ?? 41 B8 01 00 00 00 48 8D 15 ?? ?? ?? ?? 48 8B 48 20 E8 ?? ?? ?? ?? 48 8B CF");
this.GetUIObjectByName = sig.ScanText("E8 ?? ?? ?? ?? 48 8B CF 48 89 87 ?? ?? 00 00 E8 ?? ?? ?? ?? 41 B8 01 00 00 00");
this.GetUIModule = sig.ScanText("E8 ?? ?? ?? ?? 48 8B C8 48 85 C0 75 2D");
var uiModuleVtableSig = sig.GetStaticAddressFromSig("48 8D 05 ?? ?? ?? ?? 4C 89 61 28"); var uiModuleVtableSig = sig.GetStaticAddressFromSig("48 8D 05 ?? ?? ?? ?? 4C 89 61 28");
this.GetAgentModule = Marshal.ReadIntPtr(uiModuleVtableSig, 34 * IntPtr.Size); this.GetAgentModule = Marshal.ReadIntPtr(uiModuleVtableSig, 34 * IntPtr.Size);

View file

@ -2,11 +2,10 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Hooking; using Dalamud.Hooking;
namespace Dalamud.Game.Gui namespace Dalamud.Game.Gui.Toast
{ {
/// <summary> /// <summary>
/// This class facilitates interacting with and creating native toast windows. /// This class facilitates interacting with and creating native toast windows.

View file

@ -1,8 +1,6 @@
using System; using System;
using Dalamud.Game.Internal; namespace Dalamud.Game.Gui.Toast
namespace Dalamud.Game.Gui
{ {
/// <summary> /// <summary>
/// An address resolver for the <see cref="ToastGui"/> class. /// An address resolver for the <see cref="ToastGui"/> class.

View file

@ -160,27 +160,25 @@ namespace Dalamud.Game.Network
return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4); return this.processZonePacketUpHook.Original(a1, dataPtr, a3, a4);
} }
#if DEBUG // private void InjectZoneProtoPacket(byte[] data)
private void InjectZoneProtoPacket(byte[] data) // {
{ // this.zoneInjectQueue.Enqueue(data);
this.zoneInjectQueue.Enqueue(data); // }
}
private void InjectActorControl(short cat, int param1) // private void InjectActorControl(short cat, int param1)
{ // {
var packetData = new byte[] // var packetData = new byte[]
{ // {
0x14, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x17, 0x7C, 0xC5, 0x5D, 0x00, 0x00, 0x00, 0x00, // 0x14, 0x00, 0x8D, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x17, 0x7C, 0xC5, 0x5D, 0x00, 0x00, 0x00, 0x00,
0x05, 0x00, 0x48, 0xB2, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x05, 0x00, 0x48, 0xB2, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x43, 0x7F, 0x00, 0x00, // 0x00, 0x00, 0x00, 0x00, 0x43, 0x7F, 0x00, 0x00,
}; // };
//
BitConverter.GetBytes((short)cat).CopyTo(packetData, 0x10); // BitConverter.GetBytes((short)cat).CopyTo(packetData, 0x10);
//
BitConverter.GetBytes((uint)param1).CopyTo(packetData, 0x14); // BitConverter.GetBytes((uint)param1).CopyTo(packetData, 0x14);
//
this.InjectZoneProtoPacket(packetData); // this.InjectZoneProtoPacket(packetData);
} // }
#endif
} }
} }

View file

@ -17,6 +17,15 @@ namespace Dalamud.Game
private IntPtr moduleCopyPtr; private IntPtr moduleCopyPtr;
private long moduleCopyOffset; private long moduleCopyOffset;
/// <summary>
/// Initializes a new instance of the <see cref="SigScanner"/> class using the main module of the current process.
/// </summary>
/// <param name="doCopy">Whether or not to copy the module upon initialization for search operations to use, as to not get disturbed by possible hooks.</param>
public SigScanner(bool doCopy = false)
: this(Process.GetCurrentProcess().MainModule!, doCopy)
{
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="SigScanner"/> class. /// Initializes a new instance of the <see cref="SigScanner"/> class.
/// </summary> /// </summary>

View file

@ -84,31 +84,16 @@ namespace Dalamud.Game.Text.Sanitizer
}; };
} }
private static IEnumerable<string> SanitizeByLanguage( private static IEnumerable<string> SanitizeByLanguage(IEnumerable<string> unsanitizedStrings, ClientLanguage clientLanguage)
IEnumerable<string> unsanitizedStrings, ClientLanguage clientLanguage)
{ {
var sanitizedStrings = new List<string>(); return clientLanguage switch
switch (clientLanguage)
{ {
case ClientLanguage.Japanese: ClientLanguage.Japanese => unsanitizedStrings.Select(FilterUnprintableCharacters),
case ClientLanguage.English: ClientLanguage.English => unsanitizedStrings.Select(FilterUnprintableCharacters),
sanitizedStrings.AddRange(unsanitizedStrings.Select(FilterUnprintableCharacters)); ClientLanguage.German => unsanitizedStrings.Select(original => FilterByDict(FilterUnprintableCharacters(original), DESanitizationDict)),
return sanitizedStrings; ClientLanguage.French => unsanitizedStrings.Select(original => FilterByDict(FilterUnprintableCharacters(original), FRSanitizationDict)),
case ClientLanguage.German: _ => throw new ArgumentOutOfRangeException(nameof(clientLanguage), clientLanguage, null),
sanitizedStrings.AddRange( };
unsanitizedStrings.Select(
unsanitizedString =>
FilterByDict(FilterUnprintableCharacters(unsanitizedString), DESanitizationDict)));
return sanitizedStrings;
case ClientLanguage.French:
sanitizedStrings.AddRange(
unsanitizedStrings.Select(
unsanitizedString =>
FilterByDict(FilterUnprintableCharacters(unsanitizedString), FRSanitizationDict)));
return sanitizedStrings;
default:
throw new ArgumentOutOfRangeException(nameof(clientLanguage), clientLanguage, null);
}
} }
private static string FilterUnprintableCharacters(string str) private static string FilterUnprintableCharacters(string str)

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;

View file

@ -4,7 +4,6 @@ using System.Linq;
using Dalamud.Plugin; using Dalamud.Plugin;
using ImGuiNET; using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting; using Microsoft.CodeAnalysis.Scripting;
using Serilog; using Serilog;
@ -65,10 +64,10 @@ namespace Dalamud.Interface.Internal.Scratchpad
var options = ScriptOptions.Default var options = ScriptOptions.Default
.AddReferences(typeof(ImGui).Assembly) .AddReferences(typeof(ImGui).Assembly)
.AddReferences(typeof(Dalamud).Assembly) .AddReferences(typeof(Dalamud).Assembly)
.AddReferences(typeof(FFXIVClientStructs.Attributes.Addon).Assembly) // FFXIVClientStructs .AddReferences(typeof(FFXIVClientStructs.Resolver).Assembly) // FFXIVClientStructs
.AddReferences(typeof(Lumina.GameData).Assembly) // Lumina .AddReferences(typeof(Lumina.GameData).Assembly) // Lumina
.AddReferences(typeof(TerritoryType).Assembly) // Lumina.Excel .AddReferences(typeof(Lumina.Excel.GeneratedSheets.TerritoryType).Assembly) // Lumina.Excel
// .WithReferences(MetadataReference.CreateFromFile(typeof(ScratchExecutionManager).Assembly.Location)) // .WithReferences(MetadataReference.CreateFromFile(typeof(ScratchExecutionManager).Assembly.Location))
.AddImports("System") .AddImports("System")
.AddImports("System.IO") .AddImports("System.IO")
.AddImports("System.Reflection") .AddImports("System.Reflection")

View file

@ -11,11 +11,11 @@ using Dalamud.Game.ClientState.JobGauge.Enums;
using Dalamud.Game.ClientState.JobGauge.Types; using Dalamud.Game.ClientState.JobGauge.Types;
using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.SubKinds;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Game.Gui.Addons;
using Dalamud.Game.Gui.FlyText; using Dalamud.Game.Gui.FlyText;
using Dalamud.Game.Gui.Toast; using Dalamud.Game.Gui.Toast;
using Dalamud.Game.Text; using Dalamud.Game.Text;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Memory;
using Dalamud.Plugin; using Dalamud.Plugin;
using Dalamud.Utility; using Dalamud.Utility;
using ImGuiNET; using ImGuiNET;
@ -45,7 +45,6 @@ namespace Dalamud.Interface.Internal.Windows
private string inputAddonName = string.Empty; private string inputAddonName = string.Empty;
private int inputAddonIndex; private int inputAddonIndex;
private Addon resultAddon;
private IntPtr findAgentInterfacePtr; private IntPtr findAgentInterfacePtr;
@ -130,7 +129,6 @@ namespace Dalamud.Interface.Internal.Windows
/// <inheritdoc/> /// <inheritdoc/>
public override void OnClose() public override void OnClose()
{ {
this.resultAddon = null;
} }
/// <summary> /// <summary>
@ -843,22 +841,31 @@ namespace Dalamud.Interface.Internal.Windows
ImGui.Text($"{command.Key}\n -> {command.Value.HelpMessage}\n -> In help: {command.Value.ShowInHelp}\n\n"); ImGui.Text($"{command.Key}\n -> {command.Value.HelpMessage}\n -> In help: {command.Value.ShowInHelp}\n\n");
} }
private void DrawAddon() private unsafe void DrawAddon()
{ {
var gameGui = this.dalamud.Framework.Gui;
ImGui.InputText("Addon name", ref this.inputAddonName, 256); ImGui.InputText("Addon name", ref this.inputAddonName, 256);
ImGui.InputInt("Addon Index", ref this.inputAddonIndex); ImGui.InputInt("Addon Index", ref this.inputAddonIndex);
if (ImGui.Button("Get Addon")) if (this.inputAddonName.IsNullOrEmpty())
return;
var address = gameGui.GetAddonByName(this.inputAddonName, this.inputAddonIndex);
if (address == IntPtr.Zero)
{ {
this.resultAddon = this.dalamud.Framework.Gui.GetAddonByName(this.inputAddonName, this.inputAddonIndex); ImGui.Text("Null");
return;
} }
if (ImGui.Button("Find Agent")) var addon = (FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*)address;
this.findAgentInterfacePtr = this.dalamud.Framework.Gui.FindAgentInterface(this.inputAddonName); var name = MemoryHelper.ReadStringNullTerminated((IntPtr)addon->Name);
ImGui.TextUnformatted($"{name} - 0x{address.ToInt64():x}\n v:{addon->IsVisible} x:{addon->X} y:{addon->Y} s:{addon->Scale}, w:{addon->RootNode->Width}, h:{addon->RootNode->Height}");
if (this.resultAddon != null) if (ImGui.Button("Find Agent"))
{ {
ImGui.TextUnformatted($"{this.resultAddon.Name} - 0x{this.resultAddon.Address.ToInt64():x}\n v:{this.resultAddon.Visible} x:{this.resultAddon.X} y:{this.resultAddon.Y} s:{this.resultAddon.Scale}, w:{this.resultAddon.Width}, h:{this.resultAddon.Height}"); this.findAgentInterfacePtr = gameGui.FindAgentInterface(address);
} }
if (this.findAgentInterfacePtr != IntPtr.Zero) if (this.findAgentInterfacePtr != IntPtr.Zero)
@ -869,13 +876,6 @@ namespace Dalamud.Interface.Internal.Windows
if (ImGui.Button("C")) if (ImGui.Button("C"))
ImGui.SetClipboardText(this.findAgentInterfacePtr.ToInt64().ToString("x")); ImGui.SetClipboardText(this.findAgentInterfacePtr.ToInt64().ToString("x"));
} }
if (ImGui.Button("Get Base UI object"))
{
var addr = this.dalamud.Framework.Gui.GetBaseUIObject().ToInt64().ToString("x");
Log.Information("{0}", addr);
ImGui.SetClipboardText(addr);
}
} }
private void DrawAddonInspector() private void DrawAddonInspector()
@ -977,7 +977,7 @@ namespace Dalamud.Interface.Internal.Windows
if (ImGui.BeginCombo("Kind", this.flyKind.ToString())) if (ImGui.BeginCombo("Kind", this.flyKind.ToString()))
{ {
var names = Enum.GetNames(typeof(FlyTextKind)); var names = Enum.GetNames(typeof(FlyTextKind));
for (int i = 0; i < names.Length; i++) for (var i = 0; i < names.Length; i++)
{ {
if (ImGui.Selectable($"{names[i]} ({i})")) if (ImGui.Selectable($"{names[i]} ({i})"))
this.flyKind = (FlyTextKind)i; this.flyKind = (FlyTextKind)i;

View file

@ -1,5 +1,4 @@
using System; using System;
using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@ -20,7 +19,6 @@ namespace Dalamud.Memory
public static unsafe class MemoryHelper public static unsafe class MemoryHelper
{ {
private static SeStringManager seStringManager; private static SeStringManager seStringManager;
private static IntPtr handle;
#region Read #region Read
@ -174,8 +172,23 @@ namespace Dalamud.Memory
/// </remarks> /// </remarks>
/// <param name="memoryAddress">The memory address to read from.</param> /// <param name="memoryAddress">The memory address to read from.</param>
/// <returns>The read in string.</returns> /// <returns>The read in string.</returns>
public static string ReadString(IntPtr memoryAddress) public static string ReadStringNullTerminated(IntPtr memoryAddress)
=> ReadString(memoryAddress, 256); => ReadStringNullTerminated(memoryAddress, Encoding.UTF8);
/// <summary>
/// Read a string with the given encoding from a specified memory address.
/// </summary>
/// <remarks>
/// Attention! If this is an SeString, use the <see cref="SeStringManager"/> to decode or the applicable helper method.
/// </remarks>
/// <param name="memoryAddress">The memory address to read from.</param>
/// <param name="encoding">The encoding to use to decode the string.</param>
/// <returns>The read in string.</returns>
public static string ReadStringNullTerminated(IntPtr memoryAddress, Encoding encoding)
{
var buffer = ReadRawNullTerminated(memoryAddress);
return encoding.GetString(buffer);
}
/// <summary> /// <summary>
/// Read a UTF-8 encoded string from a specified memory address. /// Read a UTF-8 encoded string from a specified memory address.
@ -189,18 +202,6 @@ namespace Dalamud.Memory
public static string ReadString(IntPtr memoryAddress, int maxLength) public static string ReadString(IntPtr memoryAddress, int maxLength)
=> ReadString(memoryAddress, Encoding.UTF8, maxLength); => ReadString(memoryAddress, Encoding.UTF8, maxLength);
/// <summary>
/// Read a string with the given encoding from a specified memory address.
/// </summary>
/// <remarks>
/// Attention! If this is an SeString, use the <see cref="SeStringManager"/> to decode or the applicable helper method.
/// </remarks>
/// <param name="memoryAddress">The memory address to read from.</param>
/// <param name="encoding">The encoding to use to decode the string.</param>
/// <returns>The read in string.</returns>
public static string ReadString(IntPtr memoryAddress, Encoding encoding)
=> ReadString(memoryAddress, encoding, 256);
/// <summary> /// <summary>
/// Read a string with the given encoding from a specified memory address. /// Read a string with the given encoding from a specified memory address.
/// </summary> /// </summary>
@ -288,8 +289,20 @@ namespace Dalamud.Memory
/// </remarks> /// </remarks>
/// <param name="memoryAddress">The memory address to read from.</param> /// <param name="memoryAddress">The memory address to read from.</param>
/// <param name="value">The read in string.</param> /// <param name="value">The read in string.</param>
public static void ReadString(IntPtr memoryAddress, out string value) public static void ReadStringNullTerminated(IntPtr memoryAddress, out string value)
=> value = ReadString(memoryAddress); => value = ReadStringNullTerminated(memoryAddress);
/// <summary>
/// Read a string with the given encoding from a specified memory address.
/// </summary>
/// <remarks>
/// Attention! If this is an SeString, use the <see cref="SeStringManager"/> to decode or the applicable helper method.
/// </remarks>
/// <param name="memoryAddress">The memory address to read from.</param>
/// <param name="encoding">The encoding to use to decode the string.</param>
/// <param name="value">The read in string.</param>
public static void ReadStringNullTerminated(IntPtr memoryAddress, Encoding encoding, out string value)
=> value = ReadStringNullTerminated(memoryAddress, encoding);
/// <summary> /// <summary>
/// Read a UTF-8 encoded string from a specified memory address. /// Read a UTF-8 encoded string from a specified memory address.
@ -303,18 +316,6 @@ namespace Dalamud.Memory
public static void ReadString(IntPtr memoryAddress, out string value, int maxLength) public static void ReadString(IntPtr memoryAddress, out string value, int maxLength)
=> value = ReadString(memoryAddress, maxLength); => value = ReadString(memoryAddress, maxLength);
/// <summary>
/// Read a string with the given encoding from a specified memory address.
/// </summary>
/// <remarks>
/// Attention! If this is an SeString, use the <see cref="SeStringManager"/> to decode or the applicable helper method.
/// </remarks>
/// <param name="memoryAddress">The memory address to read from.</param>
/// <param name="encoding">The encoding to use to decode the string.</param>
/// <param name="value">The read in string.</param>
public static void ReadString(IntPtr memoryAddress, Encoding encoding, out string value)
=> value = ReadString(memoryAddress, encoding);
/// <summary> /// <summary>
/// Read a string with the given encoding from a specified memory address. /// Read a string with the given encoding from a specified memory address.
/// </summary> /// </summary>
@ -584,7 +585,7 @@ namespace Dalamud.Memory
public static void ReadProcessMemory(IntPtr memoryAddress, ref byte[] value) public static void ReadProcessMemory(IntPtr memoryAddress, ref byte[] value)
{ {
var length = value.Length; var length = value.Length;
var result = NativeFunctions.ReadProcessMemory(handle, memoryAddress, value, length, out _); var result = NativeFunctions.ReadProcessMemory((IntPtr)0xFFFFFFFF, memoryAddress, value, length, out _);
if (!result) if (!result)
throw new MemoryReadException($"Unable to read memory at 0x{memoryAddress.ToInt64():X} of length {length} (result={result})"); throw new MemoryReadException($"Unable to read memory at 0x{memoryAddress.ToInt64():X} of length {length} (result={result})");
@ -603,7 +604,7 @@ namespace Dalamud.Memory
public static void WriteProcessMemory(IntPtr memoryAddress, byte[] data) public static void WriteProcessMemory(IntPtr memoryAddress, byte[] data)
{ {
var length = data.Length; var length = data.Length;
var result = NativeFunctions.WriteProcessMemory(handle, memoryAddress, data, length, out _); var result = NativeFunctions.WriteProcessMemory((IntPtr)0xFFFFFFFF, memoryAddress, data, length, out _);
if (!result) if (!result)
throw new MemoryWriteException($"Unable to write memory at 0x{memoryAddress.ToInt64():X} of length {length} (result={result})"); throw new MemoryWriteException($"Unable to write memory at 0x{memoryAddress.ToInt64():X} of length {length} (result={result})");
@ -662,7 +663,6 @@ namespace Dalamud.Memory
internal static void Initialize(Dalamud dalamud) internal static void Initialize(Dalamud dalamud)
{ {
seStringManager = dalamud.SeStringManager; seStringManager = dalamud.SeStringManager;
handle = Process.GetCurrentProcess().Handle;
} }
} }
} }

View file

@ -1,5 +1,4 @@
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_WARNINGS
#include <cstdio> #include <cstdio>
#include <filesystem> #include <filesystem>
@ -36,12 +35,20 @@ int InitializeClrAndGetEntryPoint(
CoreCLR clr; CoreCLR clr;
SetEnvironmentVariable(L"DOTNET_MULTILEVEL_LOOKUP", L"0"); SetEnvironmentVariable(L"DOTNET_MULTILEVEL_LOOKUP", L"0");
char* env_path = std::getenv("DALAMUD_RUNTIME");
wchar_t* dotnet_path; wchar_t* dotnet_path;
wchar_t* _appdata; wchar_t* _appdata;
if (!env_path) std::wstring buffer;
buffer.resize(0);
result = GetEnvironmentVariableW(L"DALAMUD_RUNTIME", &buffer[0], 0);
if (result)
{
buffer.resize(result); // The first pass returns the required length
result = GetEnvironmentVariableW(L"DALAMUD_RUNTIME", &buffer[0], result);
dotnet_path = _wcsdup(buffer.c_str());
}
else
{ {
result = SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, &_appdata); result = SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DEFAULT, nullptr, &_appdata);
@ -54,12 +61,6 @@ int InitializeClrAndGetEntryPoint(
std::filesystem::path fs_app_data(_appdata); std::filesystem::path fs_app_data(_appdata);
dotnet_path = _wcsdup(fs_app_data.append("XIVLauncher").append("runtime").c_str()); dotnet_path = _wcsdup(fs_app_data.append("XIVLauncher").append("runtime").c_str());
} }
else
{
const size_t cSize = strlen(env_path)+1;
dotnet_path = new wchar_t[cSize];
mbstowcs (dotnet_path, env_path, cSize);
}
// =========================================================================== // // =========================================================================== //