Skip to content

Commit

Permalink
Merge pull request #8 from Drakansoul/fix-item-placement
Browse files Browse the repository at this point in the history
Fix item placement
  • Loading branch information
Drakansoul authored Jul 10, 2024
2 parents ea51c5d + 4232ca4 commit f8a0c15
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 11 deletions.
8 changes: 4 additions & 4 deletions DisPlacePlugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"Author": "Drakansoul",
"Name": "DisPlace Plugin",
"InternalName": "DisPlacePlugin",
"AssemblyVersion": "3.5.1",
"AssemblyVersion": "3.6.0",
"Punchline": "Automatically save & load furniture layouts in ANY house.",
"Description": "Automatically save & load the positions of house furniture. Copy other housing layouts. Import/export layouts from the MakePlace program.",
"ApplicableVersion": "any",
Expand All @@ -19,9 +19,9 @@
"LoadPriority": 0,
"IconUrl": "https://raw.githubusercontent.com/Drakansoul/DisPlaced/master/icon.png",
"DownloadCount": 0,
"DownloadLinkInstall": "https://github.com/Drakansoul/DisPlaced/releases/download/v3.5.1-d/DisPlacePlugin.zip",
"DownloadLinkTesting": "https://github.com/Drakansoul/DisPlaced/releases/download/v3.5.1-d/DisPlacePlugin.zip",
"DownloadLinkUpdate": "https://github.com/Drakansoul/DisPlaced/releases/download/v3.5.1-d/DisPlacePlugin.zip",
"DownloadLinkInstall": "https://github.com/Drakansoul/DisPlaced/releases/download/v3.6.0/DisPlacePlugin.zip",
"DownloadLinkTesting": "https://github.com/Drakansoul/DisPlaced/releases/download/v3.6.0/DisPlacePlugin.zip",
"DownloadLinkUpdate": "https://github.com/Drakansoul/DisPlaced/releases/download/v3.6.0/DisPlacePlugin.zip",
"_isDip17Plugin": false,
"_Dip17Channel": null
}]
38 changes: 36 additions & 2 deletions DisPlacePlugin/DisPlacePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public sealed class DisPlacePlugin : IDalamudPlugin
public delegate void SelectItemDelegate(IntPtr housingStruct, IntPtr item);
private static HookWrapper<SelectItemDelegate> SelectItemHook;

public delegate void PlaceItemDelegate(IntPtr housingStruct, IntPtr item);
private static HookWrapper<PlaceItemDelegate> PlaceItemHook;

public static bool CurrentlyPlacingItems = false;

public static bool ApplyChange = false;
Expand All @@ -49,6 +52,13 @@ public void Dispose()
{

HookManager.Dispose();
try {
Memory.Instance.SetPlaceAnywhere(false);
}
catch (Exception ex)
{
DalamudApi.PluginLog.Error(ex, "Error while calling PluginMemory.Dispose()");
}

DalamudApi.ClientState.TerritoryChanged -= TerritoryChanged;
DalamudApi.CommandManager.RemoveHandler("/displace");
Expand All @@ -75,17 +85,20 @@ public DisPlacePlugin(IDalamudPluginInterface pi)

HousingData.Init(this);
Memory.Init();
Memory.Instance.SetPlaceAnywhere(true);
LayoutManager = new SaveLayoutManager(this, Config);

DalamudApi.PluginLog.Info("DisPlace Plugin v3.5.1-d initialized");
DalamudApi.PluginLog.Info("DisPlace Plugin v3.6.0 initialized");
}
public void Initialize()
{

IsSaveLayoutHook = HookManager.Hook<UpdateLayoutDelegate>("40 53 48 83 ec 20 48 8b d9 48 8b 0d ?? ?? ?? ?? e8 ?? ?? ?? ?? 33 d2 48 8b c8 e8 ?? ?? ?? ?? 84 c0 75 ?? 38 83 ?? 01 00 00", IsSaveLayoutDetour);

SelectItemHook = HookManager.Hook<SelectItemDelegate>("48 85 D2 0F 84 49 09 00 00 53 41 56 48 83 EC 48 48 89 6C 24 60 48 8B DA 48 89 74 24 70 4C 8B F1", SelectItemDetour);


PlaceItemHook = HookManager.Hook<PlaceItemDelegate>("48 89 5C 24 10 48 89 74 24 18 57 48 83 EC 20 4c 8B 41 18 33 FF 0F B6 F2", PlaceItemDetour);

UpdateYardObjHook = HookManager.Hook<UpdateYardDelegate>("48 89 74 24 18 57 48 83 ec 20 b8 dc 02 00 00 0f b7 f2 ??", UpdateYardObj);

GetGameObjectHook = HookManager.Hook<GetObjectDelegate>("48 89 5c 24 08 48 89 74 24 10 57 48 83 ec 20 0f b7 f2 33 db 0f 1f 40 00 0f 1f 84 00 00 00 00 00", GetGameObject);
Expand Down Expand Up @@ -132,6 +145,7 @@ private void UpdateYardObj(IntPtr objectList, ushort index)

unsafe static public void SelectItemDetour(IntPtr housing, IntPtr item)
{
DalamudApi.PluginLog.Debug(string.Format("selecting item {0}",item.ToString()));
SelectItemHook.Original(housing, item);
}

Expand All @@ -140,6 +154,24 @@ unsafe static public void SelectItem(IntPtr item)
{
SelectItemDetour((IntPtr)Memory.Instance.HousingStructure, item);
}

unsafe static public void PlaceItemDetour(IntPtr housing, IntPtr item)
{
/*
The call made by the XIV client has some strange behaviour.
It can either place the item pointer passed to it or it retrieves the activeItem from the housing object.
I tried passing the active item but I believe that doing so led to more crashes.
As such I've just defaulted to the easier path of just passing in a zero pointer so that the call populates itself form the housing object.
*/
DalamudApi.PluginLog.Debug(string.Format("placing item {0}",(housing+24).ToString()));
PlaceItemHook.Original(housing, item);
}


unsafe static public void PlaceItem(IntPtr item)
{
PlaceItemDetour((IntPtr)Memory.Instance.HousingStructure, item);
}


public unsafe void PlaceItems()
Expand Down Expand Up @@ -234,6 +266,8 @@ unsafe public static void SetItemPosition(HousingItem rowItem)
MemInstance.WritePosition(position);
MemInstance.WriteRotation(rotation);

PlaceItem(nint.Zero);

rowItem.CorrectLocation = true;
rowItem.CorrectRotation = true;

Expand Down
2 changes: 1 addition & 1 deletion DisPlacePlugin/DisPlacePlugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<DalamudLibPath>$(AppData)\XIVLauncher\addon\Hooks\dev\</DalamudLibPath>
<PluginVersion>3.5.1</PluginVersion>
<PluginVersion>3.6.0</PluginVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down
81 changes: 77 additions & 4 deletions DisPlacePlugin/Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,19 @@ public unsafe class Memory
public static GetInventoryContainerDelegate GetInventoryContainer;
public delegate InventoryContainer* GetInventoryContainerDelegate(IntPtr inventoryManager, InventoryType inventoryType);

// Pointers to modify assembly to enable place anywhere.
public IntPtr placeAnywhere;
public IntPtr wallAnywhere;
public IntPtr wallmountAnywhere;
private Memory()
{
try
{
// Assembly address for asm rewrites.
placeAnywhere = DalamudApi.SigScanner.ScanText("C6 ?? ?? ?? 00 00 00 8B FE 48 89") + 6;
wallAnywhere = DalamudApi.SigScanner.ScanText("48 85 C0 74 ?? C6 87 ?? ?? 00 00 00") + 11;
wallmountAnywhere = DalamudApi.SigScanner.ScanText("c6 87 83 01 00 00 00 48 83 c4 ??") + 6;

housingModulePtr = DalamudApi.SigScanner.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 8B 52");
LayoutWorldPtr = DalamudApi.SigScanner.GetStaticAddressFromSig("48 8B D1 48 8B 0D ?? ?? ?? ?? 48 85 C9 74 0A", 3);

Expand All @@ -38,7 +47,7 @@ private Memory()
public IntPtr housingModulePtr { get; }
public IntPtr LayoutWorldPtr { get; }

public unsafe HousingModule* HousingModule => housingModulePtr != IntPtr.Zero ? (HousingModule*) Marshal.ReadIntPtr(housingModulePtr) : null;
public unsafe HousingModule* HousingModule => housingModulePtr != IntPtr.Zero ? (HousingModule*)Marshal.ReadIntPtr(housingModulePtr) : null;
public unsafe LayoutWorld* LayoutWorld => LayoutWorldPtr != IntPtr.Zero ? (LayoutWorld*)Marshal.ReadIntPtr(LayoutWorldPtr) : null;

public unsafe HousingObjectManager* CurrentManager => HousingModule->currentTerritory;
Expand Down Expand Up @@ -289,7 +298,6 @@ public unsafe HousingArea GetCurrentTerritory()
var territoryRow = DalamudApi.DataManager.GetExcelSheet<TerritoryType>().GetRow(GetTerritoryTypeId());
if (territoryRow == null)
{
LogError("Mem Cannot identify territory");
return HousingArea.None;
}

Expand All @@ -308,7 +316,7 @@ public unsafe bool IsHousingMode()
{
if (HousingStructure == null)
return false;

return HousingStructure->Mode != HousingLayoutMode.None;
}

Expand Down Expand Up @@ -338,7 +346,8 @@ public unsafe void WritePosition(Vector3 newPosition)
try
{
var item = HousingStructure->ActiveItem;
if (item == null) {
if (item == null)
{
return;
}

Expand Down Expand Up @@ -371,5 +380,69 @@ public unsafe void WriteRotation(Vector3 newRotation)
DalamudApi.PluginLog.Error(ex, "Error occured while writing rotation!");
}
}
private static void WriteProtectedBytes(IntPtr addr, byte[] b)
{
if (addr == IntPtr.Zero) return;
VirtualProtect(addr, 1, Protection.PAGE_EXECUTE_READWRITE, out var oldProtection);
Marshal.Copy(b, 0, addr, b.Length);
VirtualProtect(addr, 1, oldProtection, out _);
}

private static void WriteProtectedBytes(IntPtr addr, byte b)
{
if (addr == IntPtr.Zero) return;
WriteProtectedBytes(addr, [b]);
}

/// <summary>
/// Sets the flag for place anywhere in memory.
/// </summary>
/// <param name="state">Boolean state for if you can place anywhere.</param>
public void SetPlaceAnywhere(bool state)
{

if (placeAnywhere == IntPtr.Zero || wallAnywhere == IntPtr.Zero || wallmountAnywhere == IntPtr.Zero){
DalamudApi.PluginLog.Debug(string.Format("Cannot Set PlaceAnywhere",state.ToString()));
return;
}
DalamudApi.PluginLog.Debug(string.Format("Setting PlaceAnywhere to {0}",state.ToString()));


// The byte state from boolean.
var bstate = (byte)(state ? 1 : 0);

// Write the bytes for place anywhere.
WriteProtectedBytes(placeAnywhere, bstate);
WriteProtectedBytes(wallAnywhere, bstate);
WriteProtectedBytes(wallmountAnywhere, bstate);

// Which bytes to write.
// byte[] showcaseBytes = state ? [0x90, 0x90, 0x90, 0x90, 0x90, 0x90] : [0x88, 0x87, 0x98, 0x02, 0x00, 0x00];

// // Write bytes for showcase anywhere (nop or original bytes).
// WriteProtectedBytes(showcaseAnywhereRotate, showcaseBytes);
// WriteProtectedBytes(showcaseAnywherePlace, showcaseBytes);
}
#region Kernel32

[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, Protection flNewProtect, out Protection lpflOldProtect);

public enum Protection
{
PAGE_NOACCESS = 0x01,
PAGE_READONLY = 0x02,
PAGE_READWRITE = 0x04,
PAGE_WRITECOPY = 0x08,
PAGE_EXECUTE = 0x10,
PAGE_EXECUTE_READ = 0x20,
PAGE_EXECUTE_READWRITE = 0x40,
PAGE_EXECUTE_WRITECOPY = 0x80,
PAGE_GUARD = 0x100,
PAGE_NOCACHE = 0x200,
PAGE_WRITECOMBINE = 0x400
}

#endregion
}
}

0 comments on commit f8a0c15

Please sign in to comment.