1+ package net .gompk .pockets .mixin ;
2+
3+ import net .gompk .pockets .Pockets ;
4+ import net .minecraft .entity .player .PlayerInventory ;
5+ import net .minecraft .item .ItemStack ;
6+ import net .minecraft .item .ShieldItem ;
7+ import net .minecraft .item .Items ;
8+ import net .minecraft .entity .EquipmentSlot ;
9+ import org .spongepowered .asm .mixin .Mixin ;
10+ import org .spongepowered .asm .mixin .injection .At ;
11+ import org .spongepowered .asm .mixin .injection .Inject ;
12+ import org .spongepowered .asm .mixin .injection .callback .CallbackInfoReturnable ;
13+
14+ @ Mixin (PlayerInventory .class )
15+ public class EnhancedSlotProtectionMixin {
16+
17+ // Block insertStack method from putting items in protected slots
18+ @ Inject (method = "insertStack(Lnet/minecraft/item/ItemStack;)Z" , at = @ At ("HEAD" ), cancellable = true )
19+ private void blockInsertStack (ItemStack stack , CallbackInfoReturnable <Boolean > cir ) {
20+ PlayerInventory inventory = (PlayerInventory )(Object )this ;
21+
22+ // Try to insert into allowed slots only
23+ if (insertIntoAllowedSlots (inventory , stack )) {
24+ cir .setReturnValue (true );
25+ } else {
26+ Pockets .LOGGER .info ("POCKETS DEBUG: Failed to insert {} - no valid slots available" ,
27+ stack .getItem ().getName ().getString ());
28+ cir .setReturnValue (false );
29+ }
30+ cir .cancel ();
31+ }
32+
33+ // Override getEmptySlot to never return armor/offhand slots for regular items
34+ @ Inject (method = "getEmptySlot()I" , at = @ At ("HEAD" ), cancellable = true )
35+ private void getEmptySlotProtected (CallbackInfoReturnable <Integer > cir ) {
36+ PlayerInventory inventory = (PlayerInventory )(Object )this ;
37+
38+ // Check hotbar first (0-8)
39+ for (int i = 0 ; i <= 8 ; i ++) {
40+ if (inventory .getStack (i ).isEmpty ()) {
41+ cir .setReturnValue (i );
42+ return ;
43+ }
44+ }
45+
46+ // Check main inventory (9-35)
47+ for (int i = 9 ; i <= 35 ; i ++) {
48+ if (inventory .getStack (i ).isEmpty ()) {
49+ cir .setReturnValue (i );
50+ return ;
51+ }
52+ }
53+
54+ // Check extra slots (45-53) if they exist
55+ for (int i = 45 ; i <= 53 ; i ++) {
56+ if (i < inventory .size () && inventory .getStack (i ).isEmpty ()) {
57+ cir .setReturnValue (i );
58+ return ;
59+ }
60+ }
61+
62+ // No empty slots found - never return armor/offhand slots (36-40)
63+ cir .setReturnValue (-1 );
64+ }
65+
66+ private boolean insertIntoAllowedSlots (PlayerInventory inventory , ItemStack stack ) {
67+ // Try to add to existing stacks first
68+ if (addToExistingStacks (inventory , stack )) {
69+ return true ;
70+ }
71+
72+ // Find empty slot in allowed areas
73+ int emptySlot = getProtectedEmptySlot (inventory );
74+ if (emptySlot != -1 ) {
75+ inventory .getMainStacks ().set (emptySlot , stack .copy ());
76+ stack .setCount (0 );
77+ return true ;
78+ }
79+
80+ return false ;
81+ }
82+
83+ private boolean addToExistingStacks (PlayerInventory inventory , ItemStack stack ) {
84+ // Check hotbar (0-8)
85+ for (int i = 0 ; i <= 8 ; i ++) {
86+ ItemStack existing = inventory .getStack (i );
87+ if (canStackWith (existing , stack )) {
88+ int transferred = Math .min (stack .getCount (), existing .getMaxCount () - existing .getCount ());
89+ existing .increment (transferred );
90+ stack .decrement (transferred );
91+ if (stack .isEmpty ()) return true ;
92+ }
93+ }
94+
95+ // Check main inventory (9-35)
96+ for (int i = 9 ; i <= 35 ; i ++) {
97+ ItemStack existing = inventory .getStack (i );
98+ if (canStackWith (existing , stack )) {
99+ int transferred = Math .min (stack .getCount (), existing .getMaxCount () - existing .getCount ());
100+ existing .increment (transferred );
101+ stack .decrement (transferred );
102+ if (stack .isEmpty ()) return true ;
103+ }
104+ }
105+
106+ // Check extra slots (45-53)
107+ for (int i = 45 ; i <= 53 ; i ++) {
108+ if (i < inventory .size ()) {
109+ ItemStack existing = inventory .getStack (i );
110+ if (canStackWith (existing , stack )) {
111+ int transferred = Math .min (stack .getCount (), existing .getMaxCount () - existing .getCount ());
112+ existing .increment (transferred );
113+ stack .decrement (transferred );
114+ if (stack .isEmpty ()) return true ;
115+ }
116+ }
117+ }
118+
119+ return false ;
120+ }
121+
122+ private boolean canStackWith (ItemStack existing , ItemStack stack ) {
123+ return !existing .isEmpty () &&
124+ existing .getItem () == stack .getItem () &&
125+ existing .getCount () < existing .getMaxCount () &&
126+ ItemStack .areEqual (existing , stack );
127+ }
128+
129+ private int getProtectedEmptySlot (PlayerInventory inventory ) {
130+ // Check hotbar first (0-8)
131+ for (int i = 0 ; i <= 8 ; i ++) {
132+ if (inventory .getStack (i ).isEmpty ()) {
133+ return i ;
134+ }
135+ }
136+
137+ // Check main inventory (9-35)
138+ for (int i = 9 ; i <= 35 ; i ++) {
139+ if (inventory .getStack (i ).isEmpty ()) {
140+ return i ;
141+ }
142+ }
143+
144+ // Check extra slots (45-53)
145+ for (int i = 45 ; i <= 53 ; i ++) {
146+ if (i < inventory .size () && inventory .getStack (i ).isEmpty ()) {
147+ return i ;
148+ }
149+ }
150+
151+ return -1 ;
152+ }
153+ }
0 commit comments