InventoryItemChangeEvent

This commit is contained in:
Шандуренко Константин Владимирович 2021-09-06 19:59:55 +03:00
parent 72987ac52f
commit 8a04d7eed9
5 changed files with 118 additions and 27 deletions

View File

@ -4,6 +4,7 @@ import net.minestom.server.MinecraftServer;
import net.minestom.server.event.entity.EntityTickEvent;
import net.minestom.server.event.instance.InstanceChunkLoadEvent;
import net.minestom.server.event.instance.InstanceTickEvent;
import net.minestom.server.event.inventory.InventoryItemChangeEvent;
import net.minestom.server.event.player.PlayerChunkLoadEvent;
import net.minestom.server.event.player.PlayerMoveEvent;
import net.minestom.server.event.player.PlayerPacketEvent;
@ -23,4 +24,5 @@ public final class GlobalHandles {
public static final ListenerHandle<InstanceTickEvent> INSTANCE_TICK = EventDispatcher.getHandle(InstanceTickEvent.class);
public static final ListenerHandle<PlayerChunkLoadEvent> PLAYER_CHUNK_LOAD = EventDispatcher.getHandle(PlayerChunkLoadEvent.class);
public static final ListenerHandle<InstanceChunkLoadEvent> INSTANCE_CHUNK_LOAD = EventDispatcher.getHandle(InstanceChunkLoadEvent.class);
public static final ListenerHandle<InventoryItemChangeEvent> INVENTORY_ITEM_CHANGE_EVENT = EventDispatcher.getHandle(InventoryItemChangeEvent.class);
}

View File

@ -0,0 +1,74 @@
package net.minestom.server.event.inventory;
import net.minestom.server.event.trait.InventoryEvent;
import net.minestom.server.inventory.AbstractInventory;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Called when {@link AbstractInventory#safeItemInsert(int, ItemStack)} is being invoked.
* This event cannot be cancelled and items related to the change are already moved.
*/
@SuppressWarnings("JavadocReference")
public class InventoryItemChangeEvent implements InventoryEvent {
private final Inventory inventory;
private final PlayerInventory playerInventory;
private final int slot;
private final ItemStack previousItem;
private final ItemStack newItem;
public InventoryItemChangeEvent(@Nullable Inventory inventory, @Nullable PlayerInventory playerInventory,
int slot, @NotNull ItemStack previousItem, @NotNull ItemStack newItem) {
this.inventory = inventory;
this.playerInventory = playerInventory;
this.slot = slot;
this.previousItem = previousItem;
this.newItem = newItem;
}
/**
* Gets the changed slot number.
*
* @return the changed slot number.
*/
public int getSlot() {
return slot;
}
/**
* Gets a previous item that was on changed slot.
*
* @return a previous item that was on changed slot.
*/
public @NotNull ItemStack getPreviousItem() {
return previousItem;
}
/**
* Gets a new item on a changed slot.
*
* @return a new item on a changed slot.
*/
public @NotNull ItemStack getNewItem() {
return newItem;
}
/**
* Gets a player inventory in which an event has occurred.
* If event happened in a regular (i.e. not player) inventory, the result is null.
*
* @return null or a player inventory in which an event has occurred.
*/
public @Nullable PlayerInventory getPlayerInventory() {
return playerInventory;
}
@Override
public @Nullable Inventory getInventory() {
return inventory;
}
}

View File

@ -1,5 +1,7 @@
package net.minestom.server.inventory;
import net.minestom.server.event.GlobalHandles;
import net.minestom.server.event.inventory.InventoryItemChangeEvent;
import net.minestom.server.inventory.click.InventoryClickProcessor;
import net.minestom.server.inventory.condition.InventoryCondition;
import net.minestom.server.item.ItemStack;
@ -52,7 +54,31 @@ public abstract class AbstractInventory implements InventoryClickHandler, TagHan
safeItemInsert(slot, itemStack);
}
protected abstract void safeItemInsert(int slot, @NotNull ItemStack itemStack);
/**
* Inserts safely an item into the inventory.
* <p>
* This will update the slot for all viewers and warn the inventory that
* the window items packet is not up-to-date.
*
* @param slot the internal slot id
* @param itemStack the item to insert (use air instead of null)
*
* @throws IllegalArgumentException if the slot {@code slot} does not exist
*/
protected synchronized final void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
Check.argCondition(
!MathUtils.isBetween(slot, 0, getSize()),
"The slot {0} does not exist in this inventory",
slot
);
ItemStack previous = itemStacks[slot];
UNSAFE_itemInsert(slot, itemStack);
GlobalHandles.INVENTORY_ITEM_CHANGE_EVENT.call(getItemChangeEvent(slot, previous, itemStack));
}
protected abstract void UNSAFE_itemInsert(int slot, @NotNull ItemStack itemStack);
protected abstract InventoryItemChangeEvent getItemChangeEvent(int slot, @NotNull ItemStack previous, @NotNull ItemStack current);
public synchronized <T> @NotNull T processItemStack(@NotNull ItemStack itemStack,
@NotNull TransactionType type,

View File

@ -3,6 +3,7 @@ package net.minestom.server.inventory;
import net.kyori.adventure.text.Component;
import net.minestom.server.Viewable;
import net.minestom.server.entity.Player;
import net.minestom.server.event.inventory.InventoryItemChangeEvent;
import net.minestom.server.inventory.click.ClickType;
import net.minestom.server.inventory.click.InventoryClickResult;
import net.minestom.server.item.ItemStack;
@ -209,21 +210,17 @@ public class Inventory extends AbstractInventory implements Viewable {
}
}
/**
* Inserts safely an item into the inventory.
* <p>
* This will update the slot for all viewers and warn the inventory that
* the window items packet is not up-to-date.
*
* @param slot the internal slot id
* @param itemStack the item to insert
*/
@Override
protected synchronized void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
this.itemStacks[slot] = itemStack;
protected void UNSAFE_itemInsert(int slot, @NotNull ItemStack itemStack) {
itemStacks[slot] = itemStack;
sendPacketToViewers(new SetSlotPacket(getWindowId(), 0, (short) slot, itemStack));
}
@Override
protected InventoryItemChangeEvent getItemChangeEvent(int slot, @NotNull ItemStack previous, @NotNull ItemStack current) {
return new InventoryItemChangeEvent(this, null, slot, previous, current);
}
/**
* Creates a complete new {@link WindowItemsPacket}.
*

View File

@ -3,6 +3,7 @@ package net.minestom.server.inventory;
import net.minestom.server.entity.EquipmentSlot;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.inventory.InventoryItemChangeEvent;
import net.minestom.server.event.item.EntityEquipEvent;
import net.minestom.server.inventory.click.ClickType;
import net.minestom.server.inventory.click.InventoryClickResult;
@ -10,8 +11,6 @@ import net.minestom.server.inventory.condition.InventoryCondition;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.server.play.SetSlotPacket;
import net.minestom.server.network.packet.server.play.WindowItemsPacket;
import net.minestom.server.utils.MathUtils;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import static net.minestom.server.utils.inventory.PlayerInventoryUtils.*;
@ -149,20 +148,8 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
}
}
/**
* Inserts an item safely (synchronized) in the appropriate slot.
*
* @param slot an internal slot
* @param itemStack the item to insert at the slot
* @throws IllegalArgumentException if the slot {@code slot} does not exist
* @throws NullPointerException if {@code itemStack} is null
*/
@Override
protected synchronized void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
Check.argCondition(!MathUtils.isBetween(slot, 0, getSize()),
"The slot {0} does not exist for player", slot);
Check.notNull(itemStack, "The ItemStack cannot be null, you can set air instead");
protected void UNSAFE_itemInsert(int slot, @NotNull ItemStack itemStack) {
EquipmentSlot equipmentSlot = null;
if (slot == player.getHeldSlot()) {
equipmentSlot = EquipmentSlot.MAIN_HAND;
@ -191,6 +178,11 @@ public class PlayerInventory extends AbstractInventory implements EquipmentHandl
sendSlotRefresh((short) convertToPacketSlot(slot), itemStack);
}
@Override
protected InventoryItemChangeEvent getItemChangeEvent(int slot, @NotNull ItemStack previous, @NotNull ItemStack current) {
return new InventoryItemChangeEvent(null, this, slot, previous, current);
}
/**
* Refreshes an inventory slot.
*