Initial import of IC.Rebuild

This commit is contained in:
2026-10-13 22:55:05 +08:00
commit 16d61f7a5e
87 changed files with 17054 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
using Dalamud.Hooking;
using ICRebuild.Core;
namespace ICRebuild.Runtime;
public sealed unsafe class MovementModules(GameContext game, Configuration config, ModuleManager modules)
{
private delegate nint Move(nuint actor, nint data, uint arg);
private delegate float Speed(long actor);
private delegate void Acceleration(long actor);
private delegate long Permission(long a1, uint a2, int a3, int a4);
private delegate long Knock(long actor, float angle, float distance, float seconds, byte a5, long a6);
private delegate nint Fall(nuint a1, uint flags);
private delegate long FallCheck(long a1, long a2, long a3);
private delegate nint Forced(nint actor, float x, float y, float z, float movementParameter, nint options);
[ThreadStatic] private static HashSet<nint>? adjusted;
public HeightActivation Height { get; } = new();
public float EffectiveHeight => !modules.IsEnabled(9) ? 0 : Policies.HeightDelta(game.Ready,modules.IsEnabled(10),game.ReadDungeon(),Height.Applied);
public void Register()
{
modules.Register(11, _ => { });
modules.Register(10, _ => { }, 9);
modules.Register(9, StartHeight);
modules.Register(1, scope =>
{
Hook<Speed>? hook = null;
hook = game.Hook<Speed>(scope, Signatures.SpeedAddress, actor =>
{
var original = hook!.Original(actor);
try
{
if (!game.Ready || game.IsSlowed) return original;
return float.IsFinite(original) ? Math.Max(0, original + config.Value(1)) : original;
}
catch(Exception ex) { game.Fault(1,ex); return original; }
});
hook.Enable();
});
modules.Register(2, scope =>
{
if(game.GameVersion!=AccelerationPolicy.AuditedVersion) throw new InvalidOperationException("最大加速度仅完成 2026.09.15 客户端的字段核对。");
Hook<Acceleration>? hook = null;
hook = game.Hook<Acceleration>(scope, "40 ?? 48 ?? ?? ?? 80 79 ?? ?? 48 ?? ?? 0f 84 ?? ?? ?? ?? 48 89 7c 24 ?? 48 ?? ?? ??", actor =>
{
var frame=game.Frames.Read();
if(actor==0 || !frame.Ready || *(byte*)((nint)actor+0x3C)==0) { hook!.Original(actor); return; }
var controller=*(nint*)((nint)actor+0x20);
var owner=controller==0 ? 0 : *(nint*)(controller+0x3E0);
ref var field=ref *(float*)((nint)actor+0x44);
var prime=AccelerationPolicy.ShouldPrime(frame,owner,true,field);
AccelerationPolicy.Run(ref field,prime,()=>hook!.Original(actor));
});
hook.Enable();
});
modules.Register(3, scope =>
{
Hook<Permission>? hook = null;
hook = game.Hook<Permission>(scope, Signatures.MovePermissionAddress, (a1,a2,a3,a4) =>
game.Ready && NativeIds.MovementPermissionChecks.Contains(a2) ? 1 : hook!.Original(a1,a2,a3,a4));
hook.Enable();
});
modules.Register(4, scope =>
{
Hook<Knock>? hook = null;
hook = game.Hook<Knock>(scope, Signatures.AntiKnockAddress, (actor,angle,distance,seconds,a5,a6) =>
{
if (actor != 0 && actor == game.LocalAddress)
{ distance = config.Value(4); seconds = config.Published.KnockSeconds; }
return hook!.Original(actor,angle,distance,seconds,a5,a6);
});
hook.Enable();
});
modules.Register(5, scope =>
{
Hook<Fall>? hook = null;
hook = game.Hook<Fall>(scope, Signatures.OnSendFlag, (a1,flags) => hook!.Original(a1,game.Ready ? Policies.FallFlags(flags) : flags));
hook.Enable();
});
modules.Register(6, scope =>
{
Hook<FallCheck>? hook = null;
hook = game.Hook<FallCheck>(scope, Signatures.FallCheckPatch, (a1,a2,a3) => game.Ready ? -1 : hook!.Original(a1,a2,a3));
hook.Enable();
});
modules.Register(7, scope =>
{
if(game.GameVersion!=AccelerationPolicy.AuditedVersion) throw new InvalidOperationException("强制移动入口参数仅核对了 2026.09.15 客户端");
Hook<Forced>? hook = null;
hook = game.Hook<Forced>(scope, Signatures.FuckBewithAction, (actor,x,y,z,movementParameter,options) =>
{
// This intercepts a forced-coordinate movement path; it does not remove a status.
if(actor!=0 && actor==game.LocalAddress) return 0;
return hook!.Original(actor,x,y,z,movementParameter,options);
});
hook.Enable();
});
}
private void StartHeight(ResourceScope scope)
{
Height.Reset();
Hook<Move>? normal = null, combat = null;
normal = game.Hook<Move>(scope, Signatures.OnSendNormalMove, (actor,data,arg) => ApplyHeight(normal!.Original,actor,data,arg,false));
combat = game.Hook<Move>(scope, Signatures.OnSendCombatMove, (actor,data,arg) => ApplyHeight(combat!.Original,actor,data,arg,true));
scope.Defer(Height.Reset);
normal.Enable(); combat.Enable();
}
private nint ApplyHeight(Move original, nuint actor, nint data, uint arg, bool combat)
{
float delta;
try
{
delta=EffectiveHeight;
}
catch(Exception ex) { game.Fault(9,ex); return original(actor,data,arg); }
if (data == 0 || delta == 0) return original(actor,data,arg);
adjusted ??= [];
if (!adjusted.Add(data)) return original(actor,data,arg);
var values = (float*)data;
var first = combat ? 4 : 3;
float old = values[first], old2 = combat ? values[7] : 0;
try
{
if (!float.IsFinite(old) || (combat && !float.IsFinite(old2))) return original(actor,data,arg);
values[first] = old + delta;
if (combat) values[7] = old2 + delta;
try { return original(actor,data,arg); }
finally { values[first] = old; if (combat) values[7] = old2; }
}
finally { adjusted.Remove(data); }
}
}