Skip to content

Commit 234a9a0

Browse files
committed
Fix hook
1 parent 215bc34 commit 234a9a0

1 file changed

Lines changed: 85 additions & 31 deletions

File tree

OTAPI.Scripts/Patches/HookChestQuickStack.Server.cs

Lines changed: 85 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -43,32 +43,25 @@ partial class ChestHooks
4343
static void HookChestQuickStack(ModFwModder modder)
4444
{
4545
#if TerrariaServer_1450_OrAbove || Terraria__1450_OrAbove || tModLoader_1450_OrAbove
46-
// used for the out parameter only
47-
List<int> _blockedChests;
48-
49-
// DO NOT use GetILCursor(). The instruction body does not have jumps transformed into labels,
50-
// a process which is required to happen for the edits below to work.
51-
var ctx = new ILContext(modder.GetMethodDefinition(() => QuickStacking.Transfer(default, default, out _blockedChests, false)));
52-
ctx.Invoke((ctx) =>
5346
{
54-
var csr = new ILCursor(ctx);
55-
int count = 0;
56-
57-
while (csr.TryGotoNext(
58-
MoveType.Before,
59-
i => i.MatchLdarg(0),
60-
i => i.MatchLdloc(out _),
61-
i => i.MatchCall(typeof(QuickStacking), nameof(QuickStacking.Consolidate))
62-
))
63-
{
64-
if (++count > 2)
65-
{
66-
throw new Exception($"More than two matches of {nameof(QuickStacking.Consolidate)}.");
67-
}
47+
// DO NOT use GetILCursor(). The instruction body does not have jumps transformed into labels,
48+
// a process which is required to happen for the edits below to work.
49+
var ctx = new ILContext(modder.GetMethodDefinition(() => QuickStacking.BuildDestinationMetricsAndStackItems(default, default, default)));
6850

69-
// Both targets are preceded by a jump instruction exiting the loop
70-
var endInstruction = csr.Prev.Operand;
51+
// Hooks onto quick stacking into existing slot
52+
ctx.Invoke((ctx) =>
53+
{
54+
var csr = new ILCursor(ctx);
7155

56+
ILLabel endLabel = null!;
57+
csr.GotoNext(
58+
MoveType.After,
59+
i => i.MatchLdarg(1),
60+
i => i.MatchLdcI4(1),
61+
i => i.MatchStfld(typeof(QuickStacking.DestinationHelper), nameof(QuickStacking.DestinationHelper.transferBlocked)),
62+
i => i.MatchBr(out endLabel)
63+
);
64+
// AfterLabel is not the same as After + MoveAfterLabels for some reason
7265
csr.MoveAfterLabels();
7366

7467
// Load player ID (source.slots[0].Player.whoAmI)
@@ -86,24 +79,85 @@ static void HookChestQuickStack(ModFwModder modder)
8679

8780
// Load item
8881
// NOTE: this is very fragile, but I can't think of a way to write it better without significantly bloating the code
89-
csr.Emit(OpCodes.Ldloc_S, (byte)(count == 1 ? 6 : 9));
82+
csr.Emit(OpCodes.Ldloc_S, (byte)3);
9083

9184
// Load chest index
92-
// NOTE: this is very fragile, but I can't think of a way to write it better without significantly bloating the code
93-
csr.Emit(OpCodes.Ldloc_S, (byte)(count == 1 ? 7 : 10));
85+
csr.Emit(OpCodes.Ldarg_S, (byte)1);
9486
// ^.ChestIndex (property get)
9587
csr.Emit(OpCodes.Callvirt, modder.GetDefinition<QuickStacking.DestinationHelper>().Properties.Single(p => p.Name == "ChestIndex")!.GetMethod);
9688

9789
// Call hook
9890
csr.Emit(OpCodes.Call, modder.GetMethodDefinition(() => OTAPI.Hooks.Chest.InvokeQuickStack(default, default!, default)));
9991

10092
// Continue if handled
101-
csr.Emit(OpCodes.Brtrue, endInstruction);
93+
csr.Emit(OpCodes.Brfalse, endLabel);
94+
});
95+
}
96+
{
97+
// used for the out parameter only
98+
List<int> _blockedChests;
10299

103-
// Move after Consolidate call
104-
csr.Goto(csr.Index + 3);
105-
}
106-
});
100+
// DO NOT use GetILCursor(). The instruction body does not have jumps transformed into labels,
101+
// a process which is required to happen for the edits below to work.
102+
var ctx = new ILContext(modder.GetMethodDefinition(() => QuickStacking.Transfer(default, default, out _blockedChests, default)));
103+
104+
// Hooks onto quick stacking overflowing into a new stack
105+
ctx.Invoke((ctx) =>
106+
{
107+
var csr = new ILCursor(ctx);
108+
int count = 0;
109+
110+
while (csr.TryGotoNext(
111+
MoveType.Before,
112+
i => i.MatchLdarg(0),
113+
i => i.MatchLdloc(out _),
114+
i => i.MatchCall(typeof(QuickStacking), nameof(QuickStacking.Consolidate))
115+
))
116+
{
117+
if (++count > 2)
118+
{
119+
throw new Exception($"More than two matches of {nameof(QuickStacking.Consolidate)}.");
120+
}
121+
122+
// Both targets are preceded by a jump instruction exiting the loop
123+
var endInstruction = csr.Prev.Operand;
124+
125+
csr.MoveAfterLabels();
126+
127+
// Load player ID (source.slots[0].Player.whoAmI)
128+
// source
129+
csr.Emit(OpCodes.Ldarg_0);
130+
// ^.slots
131+
csr.Emit(OpCodes.Ldfld, modder.GetFieldDefinition(() => default(QuickStacking.SourceInventory).slots));
132+
// ^[0]
133+
csr.Emit(OpCodes.Ldc_I4_0);
134+
csr.Emit(OpCodes.Ldelem_Any, modder.GetDefinition<PlayerItemSlotID.SlotReference>());
135+
// ^.Player
136+
csr.Emit(OpCodes.Ldfld, modder.GetFieldDefinition(() => default(PlayerItemSlotID.SlotReference).Player));
137+
// ^.whoAmI
138+
csr.Emit(OpCodes.Ldfld, modder.GetFieldDefinition(() => default(Player)!.whoAmI));
139+
140+
// Load item
141+
// NOTE: this is very fragile, but I can't think of a way to write it better without significantly bloating the code
142+
csr.Emit(OpCodes.Ldloc_S, (byte)(count == 1 ? 6 : 9));
143+
144+
// Load chest index
145+
// NOTE: this is very fragile, but I can't think of a way to write it better without significantly bloating the code
146+
csr.Emit(OpCodes.Ldloc_S, (byte)(count == 1 ? 7 : 10));
147+
// ^.ChestIndex (property get)
148+
csr.Emit(OpCodes.Callvirt, modder.GetDefinition<QuickStacking.DestinationHelper>().Properties.Single(p => p.Name == "ChestIndex")!.GetMethod);
149+
150+
// Call hook
151+
csr.Emit(OpCodes.Call, modder.GetMethodDefinition(() => OTAPI.Hooks.Chest.InvokeQuickStack(default, default!, default)));
152+
153+
// Continue if handled
154+
csr.Emit(OpCodes.Brfalse, endInstruction);
155+
156+
// Move after Consolidate call
157+
csr.Goto(csr.Index + 3);
158+
}
159+
});
160+
}
107161
#else
108162
var csr = modder.GetILCursor(() => Terraria.Chest.PutItemInNearbyChest(null, default));
109163
PutItemInNearbyChest = csr.Method;

0 commit comments

Comments
 (0)