@@ -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