Skip to content

Commit

Permalink
Update party & change opcodes to hooking
Browse files Browse the repository at this point in the history
  • Loading branch information
Bluefissure committed Jan 23, 2021
1 parent 5282825 commit 8e04e7e
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 21 deletions.
31 changes: 31 additions & 0 deletions Inviter/ClientStructs/GroupManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace Inviter.ClientStructs
{
// Referred from https://github.com/aers/FFXIVClientStructs/blob/main/FFXIV/Group/GroupManager.cs

// there are actually two copies of this back to back in the exe
// maybe for 48 man raid support since the group manager can only hold 1 alliance worth of party members
[StructLayout(LayoutKind.Explicit, Size = 0x3D70)]
public unsafe struct GroupManager
{
[FieldOffset(0x0)] public fixed byte PartyMembers[0x230 * 8]; // PartyMember type
// for some reason the alliance array is size 20. it used to be 16 in old versions.
[FieldOffset(0x1180)] public fixed byte AllianceMembers[0x230 * 20]; // PartyMember type
[FieldOffset(0x3D40)] public uint Unk_3D40;
[FieldOffset(0x3D44)] public ushort Unk_3D44;
[FieldOffset(0x3D48)] public long Unk_3D48;
[FieldOffset(0x3D50)] public long Unk_3D50;
[FieldOffset(0x3D58)] public uint PartyLeaderIndex; // index of party leader in array
[FieldOffset(0x3D5C)] public byte MemberCount;
[FieldOffset(0x3D5D)] public byte Unk_3D5D;
[FieldOffset(0x3D5E)] public bool IsAlliance;
[FieldOffset(0x3D5F)] public byte Unk_3D5F; // some sort of count
[FieldOffset(0x3D60)] public byte Unk_3D60;
}
}
42 changes: 42 additions & 0 deletions Inviter/ClientStructs/PartyMember.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace Inviter.ClientStructs
{
// Referred from https://github.com/aers/FFXIVClientStructs/blob/main/FFXIV/Group/PartyMember.cs
[StructLayout(LayoutKind.Explicit, Size = 0x230)]
public unsafe struct PartyMember
{
// [FieldOffset(0x0)] public BuffList BuffList;
[FieldOffset(0x190)] public float X;
[FieldOffset(0x194)] public float Y;
[FieldOffset(0x198)] public float Z;
[FieldOffset(0x1A0)] public long Unk_1A0;
[FieldOffset(0x1A8)] public uint ObjectID;
[FieldOffset(0x1AC)] public uint Unk_ObjectID_1;
[FieldOffset(0x1B0)] public uint Unk_ObjectID_2;
[FieldOffset(0x1B4)] public uint CurrentHP;
[FieldOffset(0x1B8)] public uint MaxHP;
[FieldOffset(0x1BC)] public ushort CurrentMP;
[FieldOffset(0x1BE)] public ushort MaxMP;
[FieldOffset(0x1C0)] public ushort TerritoryType; // player zone
[FieldOffset(0x1C2)] public ushort Unk_1C2; // seems to be 0x63/99, no idea what it is
[FieldOffset(0x1C4)] public fixed byte Name[0x40]; // character name string
[FieldOffset(0x204)] public byte Sex;
[FieldOffset(0x205)] public byte ClassJob;
[FieldOffset(0x206)] public byte Level;
// 0x18 byte struct at 0x208
[FieldOffset(0x208)] public byte Unk_Struct_208__0;
[FieldOffset(0x20C)] public uint Unk_Struct_208__4;
[FieldOffset(0x210)] public ushort Unk_Struct_208__8;
[FieldOffset(0x214)] public uint Unk_Struct_208__C;
[FieldOffset(0x218)] public ushort Unk_Struct_208__10;
[FieldOffset(0x21A)] public ushort Unk_Struct_208__14;
[FieldOffset(0x220)] public byte Unk_220;

}
}
108 changes: 91 additions & 17 deletions Inviter/Inviter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
using System.Threading;
using Dalamud.Hooking;
using Dalamud.Game.Internal.Network;
using GroupManager = Inviter.ClientStructs.GroupManager;
using PartyMember = Inviter.ClientStructs.PartyMember;

namespace Inviter
{
Expand All @@ -44,14 +46,15 @@ public class Inviter : IDalamudPlugin
private IntPtr uiModulePtr;
private IntPtr uiModule;
private Int64 uiInvite;
private IntPtr groupManagerAddress;
private Dictionary<string, Int64> name2CID;

public void Dispose()
{
//easierProcessCIDHook.Dispose();
//easierProcessEurekaInviteHook.Dispose();
easierProcessCIDHook.Dispose();
// easierProcessEurekaInviteHook.Dispose();
Interface.Framework.Gui.Chat.OnChatMessage -= Chat_OnChatMessage;
Interface.Framework.Network.OnNetworkMessage -= Chat_OnNetworkMessage;
// Interface.Framework.Network.OnNetworkMessage -= Chat_OnNetworkMessage;
Interface.ClientState.TerritoryChanged -= TerritoryChanged;
Interface.CommandManager.RemoveHandler("/xinvite");
Gui?.Dispose();
Expand All @@ -70,10 +73,13 @@ public void Initialize(DalamudPluginInterface pluginInterface)
getUIModulePtr = Interface.TargetModuleScanner.ScanText("E8 ?? ?? ?? ?? 48 83 7F ?? 00 48 8B F0");
uiModulePtr = Interface.TargetModuleScanner.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 48 8D 54 24 ?? 48 83 C1 10 E8 ?? ?? ?? ??");
InitUi();
groupManagerAddress = Interface.TargetModuleScanner.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? 44 8B E7");
PluginLog.Log("===== I N V I T E R =====");
PluginLog.Log("Process Invite address {Address}", easierProcessInvitePtr);
PluginLog.Log("Process CID address {Address}", easierProcessCIDPtr);
PluginLog.Log("uiModule address {Address}", uiModule);
PluginLog.Log("uiInvite address {Address}", uiInvite);
PluginLog.Log("groupManager address {Address}", groupManagerAddress);


//Log($"EurekaInvite:{easierProcessEurekaInvitePtr}");
Expand All @@ -85,10 +91,10 @@ public void Initialize(DalamudPluginInterface pluginInterface)
new EasierProcessEurekaInviteDelegate(EasierProcessEurekaInviteDetour),
this);
*/
//easierProcessCIDHook = new Hook<EasierProcessCIDDelegate>(easierProcessCIDPtr,
// new EasierProcessCIDDelegate(EasierProcessCIDDetour),
// this);
//easierProcessCIDHook.Enable();
easierProcessCIDHook = new Hook<EasierProcessCIDDelegate>(easierProcessCIDPtr,
new EasierProcessCIDDelegate(EasierProcessCIDDetour),
this);
easierProcessCIDHook.Enable();
//easierProcessEurekaInviteHook.Enable();

Interface.CommandManager.AddHandler("/xinvite", new CommandInfo(CommandHandler)
Expand All @@ -97,7 +103,7 @@ public void Initialize(DalamudPluginInterface pluginInterface)
});
Gui = new PluginUi(this);
Interface.Framework.Gui.Chat.OnChatMessage += Chat_OnChatMessage;
Interface.Framework.Network.OnNetworkMessage += Chat_OnNetworkMessage;
// Interface.Framework.Network.OnNetworkMessage += Chat_OnNetworkMessage;
Interface.ClientState.TerritoryChanged += TerritoryChanged;
}

Expand Down Expand Up @@ -138,6 +144,23 @@ public void CommandHandler(string command, string arguments)
Interface.Framework.Gui.Chat.Print($"Auto invite is turned off");
Config.Save();
}
/*
else if (args == "party")
{
unsafe
{
GroupManager* groupManager = (GroupManager*)groupManagerAddress;
var partyMembers = (PartyMember*)groupManager->PartyMembers;
var leader = partyMembers[groupManager->PartyLeaderIndex];
string leaderName = StringFromNativeUtf8(new IntPtr(leader.Name));
Log($"MemberCount:{groupManager->MemberCount}");
Log($"LeaderIndex:{groupManager->PartyLeaderIndex}");
Log($"LeaderName:{leaderName}");
Log($"SelfName:{Interface.ClientState.LocalPlayer.Name}");
Log($"isLeader:{Interface.ClientState.LocalPlayer.Name == leaderName}");
}
}
*/
}
private void InitUi()
{
Expand All @@ -146,19 +169,19 @@ private void InitUi()
if (uiModule == IntPtr.Zero)
throw new ApplicationException("uiModule was null");
IntPtr step2 = Marshal.ReadIntPtr(uiModule) + 264;
Log($"step2:{step2}");
PluginLog.Log($"step2:0x{step2:X}");
if (step2 == IntPtr.Zero)
throw new ApplicationException("step2 was null");
IntPtr step3 = Marshal.ReadIntPtr(step2);
Log($"step3:{step3}");
PluginLog.Log($"step3:0x{step3:X}");
if (step3 == IntPtr.Zero)
throw new ApplicationException("step3 was null");
IntPtr step4 = Marshal.GetDelegateForFunctionPointer<GetMagicUIDelegate>(step3)(uiModule) + 6528;
Log($"step4:{step4}");
PluginLog.Log($"step4:0x{step4:X}");
if (step4 == (IntPtr.Zero + 6528))
throw new ApplicationException("step4 was null");
uiInvite = Marshal.ReadInt64(step4);
Log($"uiInvite:{uiInvite}");
PluginLog.Log($"uiInvite:{uiInvite:X}");
}

public void Log(string message)
Expand All @@ -177,16 +200,23 @@ public void LogError(string message)
}
private void Chat_OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction)
{
return;
if (!Config.Enable || !Config.Eureka) return;
if (direction != NetworkMessageDirection.ZoneDown)
return;
var client = Interface.ClientState.ClientLanguage == ClientLanguage.ChineseSimplified ? "cn" : "intl";
// not used after hooking the function
// https://github.com/karashiiro/MachinaWrapperJSON/blob/master/MachinaWrapper/Models/Sapphire/Ipcs.cs
// https://github.com/karashiiro/MachinaWrapperJSON/blob/master/MachinaWrapper/Models/Sapphire/Ipcs_cn.cs
// if not found, it'll be triggered when chatting and the length should be 1104.
ushort chat_opcode = (ushort)(client == "cn" ? 0x0106 : 0x0349);
ushort chat_opcode = (ushort)(client == "cn" ? 0x021e : 0x02c2);
if (opCode != chat_opcode)
return;
byte[] managedArray = new byte[32];
Marshal.Copy(dataPtr, managedArray, 0, 32);
Log("Network dataPtr");
Log(BitConverter.ToString(managedArray).Replace("-", " "));
return;
Int64 CID = Marshal.ReadInt64(dataPtr);
short world_id = Marshal.ReadInt16(dataPtr, 12);
string name = StringFromNativeUtf8(dataPtr + 16);
Expand Down Expand Up @@ -218,7 +248,6 @@ public static string StringFromNativeUtf8(IntPtr nativeUtf8)
private void Chat_OnChatMessage(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled)
{
if (!Config.Enable) return;
if (Interface.ClientState.PartyList?.Count >= 8) return; // The party list is null for now
if (Config.FilteredChannels.IndexOf((ushort)type) != -1) return;
if (Config.HiddenChatType.IndexOf(type) != -1) return;
var pattern = Config.TextPattern;
Expand All @@ -234,9 +263,39 @@ private void Chat_OnChatMessage(XivChatType type, uint senderId, ref SeString se
}
if (matched)
{

var senderPayload = sender.Payloads.Where(payload => payload is PlayerPayload).FirstOrDefault();
if (senderPayload != default(Payload) && senderPayload is PlayerPayload playerPayload)
{

if (groupManagerAddress != IntPtr.Zero)
{
unsafe
{
GroupManager* groupManager = (GroupManager*)groupManagerAddress;
if (groupManager->MemberCount >= 8)
{
Log($"Full party, won't invite.");
return;
}
else
{
if (groupManager->MemberCount > 0)
{
var partyMembers = (PartyMember*)groupManager->PartyMembers;
var leader = partyMembers[groupManager->PartyLeaderIndex];
string leaderName = StringFromNativeUtf8(new IntPtr(leader.Name));

if (Interface.ClientState.LocalPlayer.Name != leaderName)
{
Log($"Not leader, won't invite. (Leader: {leaderName})");
return;
}
}
Log($"Party Count:{groupManager->MemberCount}");
}
}
}
if (Config.Eureka)
{
Task.Run(() =>
Expand Down Expand Up @@ -284,13 +343,28 @@ public void ProcessEurekaInvite(PlayerPayload player)
Int64 CID = name2CID[playerNameKey];
_EasierProcessEurekaInvite(uiInvite, CID);
}
/*
public char EasierProcessCIDDetour(Int64 a1, Int64 a2)
{
Log($"CID hook a1:{a1}");
Log($"CID hook a2:{a2}");
IntPtr dataPtr = (IntPtr)a2;
// Log($"CID hook a1:{a1}");
// Log($"CID hook a2:{dataPtr}");
if (Config.Enable && Config.Eureka && dataPtr != IntPtr.Zero)
{
Int64 CID = Marshal.ReadInt64(dataPtr);
short world_id = Marshal.ReadInt16(dataPtr, 12);
var world = Interface.Data.GetExcelSheet<Lumina.Excel.GeneratedSheets.World>().GetRow((uint)world_id);
string name = StringFromNativeUtf8(dataPtr + 16);
Log($"{name}@{world.Name}:{CID}");
string playerNameKey = $"{name}@{world_id}";
if (!name2CID.ContainsKey(playerNameKey))
{
name2CID.Add(playerNameKey, CID);
}
}
return easierProcessCIDHook.Original(a1, a2);
}

/*
public char EasierProcessEurekaInviteDetour(Int64 a1, Int64 a2)
{
Log($"EurekaInvite hook a1:{a1}");
Expand Down
8 changes: 7 additions & 1 deletion Inviter/Inviter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
Expand All @@ -30,6 +31,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Reference Include="Dalamud">
Expand All @@ -45,7 +47,9 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\Git\_Dalamud_\Dalamud\Dalamud\bin\Debug\Lumina.dll</HintPath>
</Reference>
<Reference Include="Lumina.Generated, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Reference Include="Lumina.Excel">
<HintPath>..\..\..\..\Git\_Dalamud_\Dalamud\Dalamud\bin\Debug\Lumina.Excel.dll</HintPath>
</Reference>
<Reference Include="SDL2-CS">
<HintPath>..\..\..\..\Git\_Dalamud_\Dalamud\Dalamud\bin\Debug\SDL2-CS.dll</HintPath>
</Reference>
Expand All @@ -60,6 +64,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ClientStructs\GroupManager.cs" />
<Compile Include="ClientStructs\PartyMember.cs" />
<Compile Include="Configuration.cs" />
<Compile Include="Gui\ConfigurationWindow.cs" />
<Compile Include="Gui\Localizer.cs" />
Expand Down
6 changes: 3 additions & 3 deletions Inviter/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Inviter")]
[assembly: AssemblyCopyright("Copyright © 2020")]
[assembly: AssemblyCopyright("Copyright © Bluefissure 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.9")]
[assembly: AssemblyFileVersion("1.0.0.9")]
[assembly: AssemblyVersion("1.0.1.0")]
[assembly: AssemblyFileVersion("1.0.1.0")]

0 comments on commit 8e04e7e

Please sign in to comment.