Skip to content
This repository was archived by the owner on Jun 3, 2024. It is now read-only.

Commit dee1357

Browse files
Fix item pickup events (#193)
1 parent 9ba44fa commit dee1357

2 files changed

Lines changed: 63 additions & 22 deletions

File tree

patchwork-events-entity/src/main/java/net/patchworkmc/impl/event/entity/PlayerEvents.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public static void firePlayerSmeltedEvent(PlayerEntity player, ItemStack smelted
6161

6262
/**
6363
*
64-
* @return -1 if the event was cancelled, 0 if the event was denied, 1 if the event was accepted
64+
* @return -1 if the event was canceled, 0 if the event was denied or had no result set, and 1 if the event was allowed
6565
*/
6666
public static int onItemPickup(PlayerEntity player, ItemEntity entityItem) {
6767
Event event = new EntityItemPickupEvent(player, entityItem);

patchwork-events-entity/src/main/java/net/patchworkmc/mixin/event/entity/MixinItemEntity.java

Lines changed: 62 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package net.patchworkmc.mixin.event.entity;
2121

2222
import org.spongepowered.asm.mixin.Mixin;
23+
import org.spongepowered.asm.mixin.Shadow;
24+
import org.spongepowered.asm.mixin.Unique;
2325
import org.spongepowered.asm.mixin.injection.At;
2426
import org.spongepowered.asm.mixin.injection.At.Shift;
2527
import org.spongepowered.asm.mixin.injection.Inject;
@@ -35,34 +37,73 @@
3537

3638
@Mixin(ItemEntity.class)
3739
public abstract class MixinItemEntity {
38-
@Inject(method = "onPlayerCollision",
39-
at = @At(
40-
value = "INVOKE",
41-
shift = Shift.BEFORE,
42-
ordinal = 0,
43-
target = "net/minecraft/item/ItemStack.isEmpty()Z"
44-
)
45-
)
46-
private void onPlayerPickUpItemEntity(PlayerEntity player, CallbackInfo ci) {
47-
ItemEntity me = (ItemEntity) (Object) this;
48-
PlayerEvents.firePlayerItemPickupEvent(player, me, me.getStack().copy());
49-
}
40+
@Shadow
41+
public abstract ItemStack getStack();
42+
43+
@Shadow
44+
private int pickupDelay;
5045

51-
int eventResult;
46+
@Unique
47+
private int eventResult;
48+
49+
@Unique
50+
private int preEventStackCount;
51+
52+
@Unique
53+
private ItemStack copy;
54+
55+
// Forge just returns early from the event if the item has pickup delay, presumably
56+
// to keep it's events from being called. To maintain compatibility with potential
57+
// Fabric mods that might want to still have this method called from items that can't
58+
// be picked up yet, we'll just skip calling the events.
59+
@Unique
60+
private boolean hasPickupDelay;
61+
62+
@Inject(method = "onPlayerCollision", at = @At("HEAD"), cancellable = true)
63+
private void patchwork_checkForPickupDelay(PlayerEntity player, CallbackInfo ci) {
64+
hasPickupDelay = this.pickupDelay > 0;
65+
}
5266

5367
@Inject(method = "onPlayerCollision",
54-
at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getCount()I"),
55-
cancellable = true
68+
at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getCount()I"),
69+
cancellable = true
5670
)
57-
void patchwork_fireItemPickupEvent(PlayerEntity player, CallbackInfo ci) {
58-
eventResult = PlayerEvents.onItemPickup(player, (ItemEntity) (Object) this);
59-
if (eventResult != 1) ci.cancel();
71+
private void patchwork_fireItemPickupEvent(PlayerEntity player, CallbackInfo ci) {
72+
if (!hasPickupDelay) {
73+
preEventStackCount = getStack().getCount();
74+
eventResult = PlayerEvents.onItemPickup(player, (ItemEntity) (Object) this);
75+
76+
if (eventResult < 0) {
77+
ci.cancel();
78+
}
79+
80+
copy = getStack().copy();
81+
}
6082
}
6183

6284
@Redirect(method = "onPlayerCollision",
63-
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerInventory;insertStack(Lnet/minecraft/item/ItemStack;)Z")
85+
at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/PlayerInventory;insertStack(Lnet/minecraft/item/ItemStack;)Z")
86+
)
87+
private boolean patchwork_giveItemConditions(PlayerInventory playerInventory, ItemStack stack) {
88+
if (hasPickupDelay) {
89+
return playerInventory.insertStack(stack); // Haven't processed the event because Forge wouldn't.
90+
} else {
91+
return eventResult == 1 || preEventStackCount <= 0 || playerInventory.insertStack(stack);
92+
}
93+
}
94+
95+
@Inject(method = "onPlayerCollision",
96+
at = @At(
97+
value = "INVOKE",
98+
shift = Shift.BEFORE,
99+
ordinal = 0,
100+
target = "net/minecraft/item/ItemStack.isEmpty()Z"
101+
)
64102
)
65-
boolean patchwork_skipIfEventNotAllowed(PlayerInventory playerInventory, ItemStack stack) {
66-
return eventResult == 1 || playerInventory.insertStack(stack);
103+
private void patchwork_firePlayerItemPickupEvent(PlayerEntity player, CallbackInfo ci) {
104+
if (!hasPickupDelay) {
105+
copy.setCount(copy.getCount() - getStack().getCount());
106+
PlayerEvents.firePlayerItemPickupEvent(player, (ItemEntity) (Object) this, copy);
107+
}
67108
}
68109
}

0 commit comments

Comments
 (0)