mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-12 10:21:39 +01:00
InventoryModifier to AbstractInventory and additional methods for inventories
This commit is contained in:
parent
ca41365453
commit
fdfd20e255
@ -6,8 +6,9 @@ import net.minestom.server.entity.GameMode;
|
||||
import net.minestom.server.entity.type.decoration.EntityItemFrame;
|
||||
import net.minestom.server.instance.Instance;
|
||||
import net.minestom.server.instance.InstanceManager;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.item.metadata.MapMeta;
|
||||
import net.minestom.server.item.meta.MapMeta;
|
||||
import net.minestom.server.map.Framebuffer;
|
||||
import net.minestom.server.map.LargeFramebuffer;
|
||||
import net.minestom.server.map.MapColors;
|
||||
@ -67,8 +68,9 @@ public class Demo {
|
||||
private static void createFrame(Instance instance, int id, int x, int y, int z) {
|
||||
EntityItemFrame itemFrame = new EntityItemFrame(new Position(x, y, z), EntityItemFrame.ItemFrameOrientation.NORTH);
|
||||
itemFrame.getPosition().setYaw(180f);
|
||||
ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1);
|
||||
map.setItemMeta(new MapMeta(id));
|
||||
ItemStack map = ItemStack.builder(Material.FILLED_MAP)
|
||||
.meta(new MapMeta.Builder().mapId(id).build())
|
||||
.build();
|
||||
itemFrame.setItemStack(map);
|
||||
itemFrame.setInstance(instance);
|
||||
itemFrame.setCustomNameVisible(true);
|
||||
|
@ -4,7 +4,7 @@ import net.minestom.server.entity.Entity;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.instance.block.BlockFace;
|
||||
import net.minestom.server.inventory.Inventory;
|
||||
import net.minestom.server.inventory.InventoryModifier;
|
||||
import net.minestom.server.inventory.AbstractInventory;
|
||||
import net.minestom.server.inventory.PlayerInventory;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
||||
@ -48,12 +48,12 @@ public class FakePlayerController {
|
||||
*/
|
||||
public void clickWindow(boolean playerInventory, short slot, byte button, short action, int mode) {
|
||||
Inventory inventory = playerInventory ? null : fakePlayer.getOpenInventory();
|
||||
InventoryModifier inventoryModifier = inventory == null ? fakePlayer.getInventory() : inventory;
|
||||
playerInventory = inventoryModifier instanceof PlayerInventory;
|
||||
AbstractInventory abstractInventory = inventory == null ? fakePlayer.getInventory() : inventory;
|
||||
playerInventory = abstractInventory instanceof PlayerInventory;
|
||||
|
||||
slot = playerInventory ? (short) PlayerInventoryUtils.convertToPacketSlot(slot) : slot;
|
||||
|
||||
ItemStack itemStack = inventoryModifier.getItemStack(slot);
|
||||
ItemStack itemStack = abstractInventory.getItemStack(slot);
|
||||
|
||||
ClientClickWindowPacket clickWindowPacket = new ClientClickWindowPacket();
|
||||
clickWindowPacket.windowId = playerInventory ? 0 : inventory.getWindowId();
|
||||
|
@ -0,0 +1,316 @@
|
||||
package net.minestom.server.inventory;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minestom.server.inventory.condition.InventoryCondition;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.StackingRule;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Represents an inventory where items can be modified/retrieved.
|
||||
*/
|
||||
public abstract class AbstractInventory {
|
||||
|
||||
/**
|
||||
* Sets an {@link ItemStack} at the specified slot and send relevant update to the viewer(s).
|
||||
*
|
||||
* @param slot the slot to set the item
|
||||
* @param itemStack the item to set
|
||||
*/
|
||||
public abstract void setItemStack(int slot, @NotNull ItemStack itemStack);
|
||||
|
||||
protected abstract void safeItemInsert(int slot, @NotNull ItemStack itemStack);
|
||||
|
||||
/**
|
||||
* Adds an {@link ItemStack} to the inventory and sends relevant update to the viewer(s).
|
||||
* <p>
|
||||
* Even the item cannot be fully added, the amount of {@code itemStack} will be updated.
|
||||
*
|
||||
* @param itemStack the item to add
|
||||
* @return true if the item has been successfully fully added, false otherwise
|
||||
*/
|
||||
public boolean addItemStack(@NotNull ItemStack itemStack) {
|
||||
Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
final StackingRule stackingRule = itemStack.getStackingRule();
|
||||
for (int i = 0; i < getInnerSize(); i++) {
|
||||
ItemStack inventoryItem = getItemStack(i);
|
||||
if (inventoryItem.isAir()) {
|
||||
continue;
|
||||
}
|
||||
if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
|
||||
final int itemAmount = stackingRule.getAmount(inventoryItem);
|
||||
if (itemAmount == stackingRule.getMaxSize())
|
||||
continue;
|
||||
final int itemStackAmount = stackingRule.getAmount(itemStack);
|
||||
final int totalAmount = itemStackAmount + itemAmount;
|
||||
if (!stackingRule.canApply(itemStack, totalAmount)) {
|
||||
// Slot cannot accept the whole item, reduce amount to 'itemStack'
|
||||
itemChangesMap.put(i, stackingRule.apply(inventoryItem, stackingRule.getMaxSize()));
|
||||
itemStack = stackingRule.apply(itemStack, totalAmount - stackingRule.getMaxSize());
|
||||
} else {
|
||||
// Slot can accept the whole item
|
||||
itemChangesMap.put(i, inventoryItem.withAmount(totalAmount));
|
||||
itemStack = ItemStack.AIR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < getInnerSize(); i++) {
|
||||
ItemStack inventoryItem = getItemStack(i);
|
||||
if (!inventoryItem.isAir()) {
|
||||
continue;
|
||||
}
|
||||
// Fill the slot
|
||||
itemChangesMap.put(i, itemStack);
|
||||
itemStack = ItemStack.AIR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (itemStack.isAir()) {
|
||||
// Item can be fully placed inside the inventory, do so
|
||||
itemChangesMap.forEach(this::safeItemInsert);
|
||||
return true;
|
||||
} else {
|
||||
// Inventory cannot accept the item fully
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds {@link ItemStack}s to the inventory and sends relevant updates to the viewer(s).
|
||||
* <p>
|
||||
* Even items cannot be fully added, the amount of {@code itemStack}s will be updated.
|
||||
*
|
||||
* @param itemStacks items to add
|
||||
* @return list of itemstacks that could not be successfully fully added, empty list otherwise
|
||||
*/
|
||||
public List<ItemStack> addItemStacks(@NotNull List<ItemStack> itemStacks) {
|
||||
List<ItemStack> result = new ArrayList<>();
|
||||
itemStacks.forEach(itemStack -> {
|
||||
if (!addItemStack(itemStack)) {
|
||||
result.add(itemStack);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether {@link ItemStack} can be fully added to the inventory.
|
||||
*
|
||||
* @param itemStack the item to be checked
|
||||
* @return true if the item can be fully added to the inventory, false otherwise
|
||||
*/
|
||||
public boolean canAddItemStack(@NotNull ItemStack itemStack) {
|
||||
final StackingRule stackingRule = itemStack.getStackingRule();
|
||||
int amountLeft = itemStack.getAmount();
|
||||
for (int i = 0; i < getInnerSize(); i++) {
|
||||
ItemStack inventoryItem = getItemStack(i);
|
||||
if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
|
||||
final int itemAmount = stackingRule.getAmount(inventoryItem);
|
||||
if (itemAmount == stackingRule.getMaxSize())
|
||||
continue;
|
||||
if (!stackingRule.canApply(itemStack, amountLeft + itemAmount)) {
|
||||
// Slot cannot accept the whole item, reduce amount to 'itemStack'
|
||||
amountLeft -= stackingRule.getMaxSize() - itemAmount;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else if (inventoryItem.isAir()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether {@link ItemStack}s can be fully added to the inventory.
|
||||
*
|
||||
* @param itemStacks items to be checked
|
||||
* @return true if all the items can be fully added to the inventory, false otherwise
|
||||
*/
|
||||
public boolean canAddItemStacks(@NotNull List<ItemStack> itemStacks) {
|
||||
return itemStacks.stream().allMatch(this::canAddItemStack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an {@link ItemStack} from the inventory and sends relevant update to the viewer(s).
|
||||
* <p>
|
||||
* Even the item cannot be fully taken, the amount of {@code itemStack} will be updated.
|
||||
*
|
||||
* @param itemStack the item to take
|
||||
* @return true if the item has been successfully fully taken, false otherwise
|
||||
*/
|
||||
public boolean takeItemStack(@NotNull ItemStack itemStack) {
|
||||
Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
final StackingRule stackingRule = itemStack.getStackingRule();
|
||||
for (int i = 0; i < getInnerSize(); i++) {
|
||||
ItemStack inventoryItem = getItemStack(i);
|
||||
if (inventoryItem.isAir()) {
|
||||
continue;
|
||||
}
|
||||
if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
|
||||
final int itemAmount = stackingRule.getAmount(inventoryItem);
|
||||
final int itemStackAmount = stackingRule.getAmount(itemStack);
|
||||
if (itemStackAmount < itemAmount) {
|
||||
itemChangesMap.put(i, stackingRule.apply(inventoryItem, itemAmount - itemStackAmount));
|
||||
itemStack = ItemStack.AIR;
|
||||
break;
|
||||
}
|
||||
itemChangesMap.put(i, ItemStack.AIR);
|
||||
itemStack = itemStack.withAmount(amount -> amount - itemAmount);
|
||||
if (itemStack.getAmount() == 0) {
|
||||
itemStack = ItemStack.AIR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (itemStack.isAir()) {
|
||||
// Item can be fully taken from the inventory, do so
|
||||
itemChangesMap.forEach(this::safeItemInsert);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes {@link ItemStack}s from the inventory and sends relevant updates to the viewer(s).
|
||||
* <p>
|
||||
* Even items cannot be fully taken, the amount of {@code itemStack}s will be updated.
|
||||
*
|
||||
* @param itemStacks items to take
|
||||
* @return list of itemstacks that could not be successfully fully taken, empty list otherwise
|
||||
*/
|
||||
public List<ItemStack> takeItemStacks(@NotNull List<ItemStack> itemStacks) {
|
||||
List<ItemStack> result = new ArrayList<>();
|
||||
itemStacks.forEach(itemStack -> {
|
||||
if (!takeItemStack(itemStack)) {
|
||||
result.add(itemStack);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether {@link ItemStack} can be fully taken from the inventory.
|
||||
*
|
||||
* @param itemStack the item to be checked
|
||||
* @return true if the item can be fully taken from the inventory, false otherwise
|
||||
*/
|
||||
public boolean canTakeItemStack(@NotNull ItemStack itemStack) {
|
||||
final StackingRule stackingRule = itemStack.getStackingRule();
|
||||
for (int i = 0; i < getInnerSize(); i++) {
|
||||
ItemStack inventoryItem = getItemStack(i);
|
||||
if (inventoryItem.isAir()) {
|
||||
continue;
|
||||
}
|
||||
if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
|
||||
final int itemAmount = stackingRule.getAmount(inventoryItem);
|
||||
final int itemStackAmount = stackingRule.getAmount(itemStack);
|
||||
if (itemStackAmount <= itemAmount) {
|
||||
return true;
|
||||
}
|
||||
itemStack = itemStack.withAmount(amount -> amount - itemAmount);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether {@link ItemStack}s can be fully taken from the inventory.
|
||||
*
|
||||
* @param itemStacks items to be checked
|
||||
* @return true if all the items can be fully taken from the inventory, false otherwise
|
||||
*/
|
||||
public boolean canTakeItemStacks(@NotNull List<ItemStack> itemStacks) {
|
||||
return itemStacks.stream().allMatch(this::canTakeItemStack);
|
||||
}
|
||||
|
||||
public void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
||||
var currentItem = getItemStack(slot);
|
||||
setItemStack(slot, operator.apply(currentItem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the inventory and send relevant update to the viewer(s).
|
||||
*/
|
||||
public abstract void clear();
|
||||
|
||||
/**
|
||||
* Gets the {@link ItemStack} at the specified slot.
|
||||
*
|
||||
* @param slot the slot to check
|
||||
* @return the item in the slot {@code slot}
|
||||
*/
|
||||
@NotNull
|
||||
public abstract ItemStack getItemStack(int slot);
|
||||
|
||||
/**
|
||||
* Gets all the {@link ItemStack} in the inventory.
|
||||
* <p>
|
||||
* Be aware that the returned array does not need to be the original one,
|
||||
* meaning that modifying it directly may not work.
|
||||
*
|
||||
* @return an array containing all the inventory's items
|
||||
*/
|
||||
@NotNull
|
||||
public abstract ItemStack[] getItemStacks();
|
||||
|
||||
/**
|
||||
* Gets the size of the inventory.
|
||||
*
|
||||
* @return the inventory's size
|
||||
*/
|
||||
public abstract int getSize();
|
||||
|
||||
/**
|
||||
* Gets the size of the "inner inventory" (which includes only "usable" slots).
|
||||
*
|
||||
* @return inner inventory's size
|
||||
*/
|
||||
public int getInnerSize() {
|
||||
return getSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the {@link InventoryCondition} of this inventory.
|
||||
*
|
||||
* @return a modifiable {@link List} containing all the inventory conditions
|
||||
*/
|
||||
@NotNull
|
||||
public abstract List<InventoryCondition> getInventoryConditions();
|
||||
|
||||
/**
|
||||
* Adds a new {@link InventoryCondition} to this inventory.
|
||||
*
|
||||
* @param inventoryCondition the inventory condition to add
|
||||
*/
|
||||
public abstract void addInventoryCondition(@NotNull InventoryCondition inventoryCondition);
|
||||
|
||||
/**
|
||||
* Places all the items of {@code itemStacks} into the internal array.
|
||||
*
|
||||
* @param itemStacks the array to copy the content from
|
||||
* @throws IllegalArgumentException if the size of the array is not equal to {@link #getSize()}
|
||||
* @throws NullPointerException if {@code itemStacks} contains one null element or more
|
||||
*/
|
||||
public void copyContents(@NotNull ItemStack[] itemStacks) {
|
||||
Check.argCondition(itemStacks.length != getSize(),
|
||||
"The size of the array has to be of the same size as the inventory: " + getSize());
|
||||
|
||||
for (int i = 0; i < itemStacks.length; i++) {
|
||||
final ItemStack itemStack = itemStacks[i];
|
||||
Check.notNull(itemStack, "The item array cannot contain any null element!");
|
||||
setItemStack(i, itemStack);
|
||||
}
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ import java.util.function.UnaryOperator;
|
||||
* You can create one with {@link Inventory#Inventory(InventoryType, String)} or by making your own subclass.
|
||||
* It can then be opened using {@link Player#openInventory(Inventory)}.
|
||||
*/
|
||||
public class Inventory implements InventoryModifier, InventoryClickHandler, Viewable, DataContainer {
|
||||
public class Inventory extends AbstractInventory implements InventoryClickHandler, Viewable, DataContainer {
|
||||
|
||||
// incremented each time an inventory is created (used in the window packets)
|
||||
private static final AtomicInteger LAST_INVENTORY_ID = new AtomicInteger();
|
||||
@ -150,19 +150,13 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
||||
@Override
|
||||
public synchronized boolean addItemStack(@NotNull ItemStack itemStack) {
|
||||
// Make the method synchronized
|
||||
return InventoryModifier.super.addItemStack(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean addItemStack(@NotNull ItemStack itemStack, int startSlot, int endSlot) {
|
||||
// Make the method synchronized
|
||||
return InventoryModifier.super.addItemStack(itemStack, startSlot, endSlot);
|
||||
return super.addItemStack(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
||||
// Make the method synchronized
|
||||
InventoryModifier.super.replaceItemStack(slot, operator);
|
||||
super.replaceItemStack(slot, operator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -299,7 +293,8 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
||||
* @param slot the internal slot id
|
||||
* @param itemStack the item to insert
|
||||
*/
|
||||
private synchronized void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
|
||||
@Override
|
||||
protected synchronized void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
|
||||
this.itemStacks[slot] = itemStack;
|
||||
SetSlotPacket setSlotPacket = new SetSlotPacket();
|
||||
setSlotPacket.windowId = getWindowId();
|
||||
|
@ -1,145 +0,0 @@
|
||||
package net.minestom.server.inventory;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minestom.server.inventory.condition.InventoryCondition;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.item.StackingRule;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Represents an inventory where items can be modified/retrieved.
|
||||
*/
|
||||
public interface InventoryModifier {
|
||||
|
||||
/**
|
||||
* Sets an {@link ItemStack} at the specified slot and send relevant update to the viewer(s).
|
||||
*
|
||||
* @param slot the slot to set the item
|
||||
* @param itemStack the item to set
|
||||
*/
|
||||
void setItemStack(int slot, @NotNull ItemStack itemStack);
|
||||
|
||||
/**
|
||||
* Adds an {@link ItemStack} to the inventory and send relevant update to the viewer(s).
|
||||
* <p>
|
||||
* Even the item cannot be fully added, the amount of {@code itemStack} will be updated.
|
||||
*
|
||||
* @param itemStack the item to add
|
||||
* @return true if the item has been successfully fully added, false otherwise
|
||||
*/
|
||||
default boolean addItemStack(@NotNull ItemStack itemStack) {
|
||||
return addItemStack(itemStack, 0, getSize());
|
||||
}
|
||||
|
||||
default boolean addItemStack(@NotNull ItemStack itemStack, int startSlot, int endSlot) {
|
||||
Int2ObjectMap<ItemStack> itemChangesMap = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
final StackingRule stackingRule = itemStack.getStackingRule();
|
||||
for (int i = startSlot; i < endSlot; i++) {
|
||||
ItemStack inventoryItem = getItemStack(i);
|
||||
if (stackingRule.canBeStacked(itemStack, inventoryItem)) {
|
||||
final int itemAmount = stackingRule.getAmount(inventoryItem);
|
||||
if (itemAmount == stackingRule.getMaxSize())
|
||||
continue;
|
||||
final int itemStackAmount = stackingRule.getAmount(itemStack);
|
||||
final int totalAmount = itemStackAmount + itemAmount;
|
||||
if (!stackingRule.canApply(itemStack, totalAmount)) {
|
||||
// Slot cannot accept the whole item, reduce amount to 'itemStack'
|
||||
itemChangesMap.put(i, stackingRule.apply(inventoryItem, stackingRule.getMaxSize()));
|
||||
itemStack = stackingRule.apply(itemStack, totalAmount - stackingRule.getMaxSize());
|
||||
} else {
|
||||
// Slot can accept the whole item
|
||||
itemChangesMap.put(i, inventoryItem.withAmount(totalAmount));
|
||||
itemStack = ItemStack.AIR;
|
||||
break;
|
||||
}
|
||||
} else if (inventoryItem.isAir()) {
|
||||
// Fill the slot
|
||||
itemChangesMap.put(i, itemStack);
|
||||
itemStack = ItemStack.AIR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemStack.isAir()) {
|
||||
// Item can be fully placed inside the inventory, do so
|
||||
itemChangesMap.forEach(this::setItemStack);
|
||||
return true;
|
||||
} else {
|
||||
// Inventory cannot accept the item fully
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
||||
var currentItem = getItemStack(slot);
|
||||
setItemStack(slot, operator.apply(currentItem));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the inventory and send relevant update to the viewer(s).
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Gets the {@link ItemStack} at the specified slot.
|
||||
*
|
||||
* @param slot the slot to check
|
||||
* @return the item in the slot {@code slot}
|
||||
*/
|
||||
@NotNull ItemStack getItemStack(int slot);
|
||||
|
||||
/**
|
||||
* Gets all the {@link ItemStack} in the inventory.
|
||||
* <p>
|
||||
* Be aware that the returned array does not need to be the original one,
|
||||
* meaning that modifying it directly may not work.
|
||||
*
|
||||
* @return an array containing all the inventory's items
|
||||
*/
|
||||
@NotNull ItemStack[] getItemStacks();
|
||||
|
||||
/**
|
||||
* Gets the size of the inventory.
|
||||
*
|
||||
* @return the inventory's size
|
||||
*/
|
||||
int getSize();
|
||||
|
||||
/**
|
||||
* Gets all the {@link InventoryCondition} of this inventory.
|
||||
*
|
||||
* @return a modifiable {@link List} containing all the inventory conditions
|
||||
*/
|
||||
@NotNull List<InventoryCondition> getInventoryConditions();
|
||||
|
||||
/**
|
||||
* Adds a new {@link InventoryCondition} to this inventory.
|
||||
*
|
||||
* @param inventoryCondition the inventory condition to add
|
||||
*/
|
||||
void addInventoryCondition(@NotNull InventoryCondition inventoryCondition);
|
||||
|
||||
/**
|
||||
* Places all the items of {@code itemStacks} into the internal array.
|
||||
*
|
||||
* @param itemStacks the array to copy the content from
|
||||
* @throws IllegalArgumentException if the size of the array is not equal to {@link #getSize()}
|
||||
* @throws NullPointerException if {@code itemStacks} contains one null element or more
|
||||
*/
|
||||
default void copyContents(@NotNull ItemStack[] itemStacks) {
|
||||
Check.argCondition(itemStacks.length != getSize(),
|
||||
"The size of the array has to be of the same size as the inventory: " + getSize());
|
||||
|
||||
for (int i = 0; i < itemStacks.length; i++) {
|
||||
final ItemStack itemStack = itemStacks[i];
|
||||
Check.notNull(itemStack, "The item array cannot contain any null element!");
|
||||
setItemStack(i, itemStack);
|
||||
}
|
||||
}
|
||||
}
|
@ -30,9 +30,10 @@ import static net.minestom.server.utils.inventory.PlayerInventoryUtils.*;
|
||||
/**
|
||||
* Represents the inventory of a {@link Player}, retrieved with {@link Player#getInventory()}.
|
||||
*/
|
||||
public class PlayerInventory implements InventoryModifier, InventoryClickHandler, EquipmentHandler, DataContainer {
|
||||
public class PlayerInventory extends AbstractInventory implements InventoryClickHandler, EquipmentHandler, DataContainer {
|
||||
|
||||
public static final int INVENTORY_SIZE = 46;
|
||||
public static final int INNER_INVENTORY_SIZE = 36;
|
||||
|
||||
protected final Player player;
|
||||
protected final ItemStack[] itemStacks = new ItemStack[INVENTORY_SIZE];
|
||||
@ -93,24 +94,13 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
|
||||
return false;
|
||||
|
||||
itemStack = addItemStackEvent.getItemStack();
|
||||
return InventoryModifier.super.addItemStack(itemStack, 0, getSize() - 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean addItemStack(@NotNull ItemStack itemStack, int startSlot, int endSlot) {
|
||||
PlayerAddItemStackEvent addItemStackEvent = new PlayerAddItemStackEvent(player, itemStack);
|
||||
player.callEvent(PlayerAddItemStackEvent.class, addItemStackEvent);
|
||||
if (addItemStackEvent.isCancelled())
|
||||
return false;
|
||||
|
||||
itemStack = addItemStackEvent.getItemStack();
|
||||
return InventoryModifier.super.addItemStack(itemStack, startSlot, endSlot);
|
||||
return super.addItemStack(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
||||
// Make the method synchronized
|
||||
InventoryModifier.super.replaceItemStack(slot, operator);
|
||||
super.replaceItemStack(slot, operator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -130,6 +120,11 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
|
||||
return INVENTORY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInnerSize() {
|
||||
return INNER_INVENTORY_SIZE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ItemStack getItemInMainHand() {
|
||||
@ -237,6 +232,7 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
|
||||
* @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 " + slot + " does not exist for player");
|
||||
|
@ -1,11 +1,11 @@
|
||||
package net.minestom.server.inventory.condition;
|
||||
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.inventory.InventoryModifier;
|
||||
import net.minestom.server.inventory.AbstractInventory;
|
||||
import net.minestom.server.inventory.click.ClickType;
|
||||
|
||||
/**
|
||||
* Can be added to any {@link InventoryModifier}
|
||||
* Can be added to any {@link AbstractInventory}
|
||||
* using {@link net.minestom.server.inventory.Inventory#addInventoryCondition(InventoryCondition)}
|
||||
* or {@link net.minestom.server.inventory.PlayerInventory#addInventoryCondition(InventoryCondition)}
|
||||
* in order to listen to any issued clicks.
|
||||
|
278
src/main/java/net/minestom/server/item/meta/MapMeta.java
Normal file
278
src/main/java/net/minestom/server/item/meta/MapMeta.java
Normal file
@ -0,0 +1,278 @@
|
||||
package net.minestom.server.item.meta;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import net.minestom.server.item.ItemMeta;
|
||||
import net.minestom.server.item.ItemMetaBuilder;
|
||||
import net.minestom.server.utils.clone.PublicCloneable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTList;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MapMeta extends ItemMeta {
|
||||
|
||||
private final int mapId;
|
||||
private final int mapScaleDirection;
|
||||
private final List<MapDecoration> decorations;
|
||||
private final Color mapColor;
|
||||
|
||||
protected MapMeta(ItemMetaBuilder metaBuilder,
|
||||
int mapId,
|
||||
int mapScaleDirection,
|
||||
@NotNull List<MapDecoration> decorations,
|
||||
@NotNull Color mapColor) {
|
||||
super(metaBuilder);
|
||||
this.mapId = mapId;
|
||||
this.mapScaleDirection = mapScaleDirection;
|
||||
this.decorations = decorations;
|
||||
this.mapColor = mapColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map id.
|
||||
*
|
||||
* @return the map id
|
||||
*/
|
||||
public int getMapId() {
|
||||
return mapId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map scale direction.
|
||||
*
|
||||
* @return the map scale direction
|
||||
*/
|
||||
public int getMapScaleDirection() {
|
||||
return mapScaleDirection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map decorations.
|
||||
*
|
||||
* @return a modifiable list containing all the map decorations
|
||||
*/
|
||||
public List<MapDecoration> getDecorations() {
|
||||
return decorations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map color.
|
||||
*
|
||||
* @return the map color
|
||||
* @deprecated Use {@link #getMapColor()}
|
||||
*/
|
||||
@Deprecated
|
||||
public ChatColor getLegacyMapColor() {
|
||||
return this.mapColor.asLegacyChatColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the map color.
|
||||
*
|
||||
* @return the map color
|
||||
*/
|
||||
public @NotNull Color getMapColor() {
|
||||
return this.mapColor;
|
||||
}
|
||||
|
||||
public static class Builder extends ItemMetaBuilder {
|
||||
|
||||
private int mapId;
|
||||
private int mapScaleDirection = 1;
|
||||
private List<MapDecoration> decorations = new CopyOnWriteArrayList<>();
|
||||
private Color mapColor = new Color(0, 0, 0);
|
||||
|
||||
public Builder mapId(int value) {
|
||||
this.mapId = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mapScaleDirection(int value) {
|
||||
this.mapScaleDirection = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder decorations(List<MapDecoration> value) {
|
||||
this.decorations = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder mapColor(Color value) {
|
||||
this.mapColor = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ItemMeta build() {
|
||||
return new MapMeta(this, mapId, mapScaleDirection, decorations, mapColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(@NotNull NBTCompound compound) {
|
||||
if (compound.containsKey("map")) {
|
||||
this.mapId = compound.getAsInt("map");
|
||||
}
|
||||
|
||||
if (compound.containsKey("map_scale_direction")) {
|
||||
this.mapScaleDirection = compound.getAsInt("map_scale_direction");
|
||||
}
|
||||
|
||||
if (compound.containsKey("Decorations")) {
|
||||
final NBTList<NBTCompound> decorationsList = compound.getList("Decorations");
|
||||
for (NBTCompound decorationCompound : decorationsList) {
|
||||
final String id = decorationCompound.getString("id");
|
||||
final byte type = decorationCompound.getAsByte("type");
|
||||
byte x = 0;
|
||||
|
||||
if (decorationCompound.containsKey("x")) {
|
||||
x = decorationCompound.getAsByte("x");
|
||||
}
|
||||
|
||||
byte z = 0;
|
||||
if (decorationCompound.containsKey("z")) {
|
||||
z = decorationCompound.getAsByte("z");
|
||||
}
|
||||
|
||||
double rotation = 0.0;
|
||||
if (decorationCompound.containsKey("rot")) {
|
||||
rotation = decorationCompound.getAsDouble("rot");
|
||||
}
|
||||
|
||||
this.decorations.add(new MapDecoration(id, type, x, z, rotation));
|
||||
}
|
||||
}
|
||||
|
||||
if (compound.containsKey("display")) {
|
||||
final NBTCompound displayCompound = compound.getCompound("display");
|
||||
if (displayCompound.containsKey("MapColor")) {
|
||||
this.mapColor = new Color(displayCompound.getAsInt("MapColor"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull NBTCompound compound) {
|
||||
compound.setInt("map", mapId);
|
||||
|
||||
compound.setInt("map_scale_direction", mapScaleDirection);
|
||||
|
||||
if (!decorations.isEmpty()) {
|
||||
NBTList<NBTCompound> decorationsList = new NBTList<>(NBTTypes.TAG_Compound);
|
||||
for (MapDecoration decoration : decorations) {
|
||||
NBTCompound decorationCompound = new NBTCompound();
|
||||
decorationCompound.setString("id", decoration.getId());
|
||||
decorationCompound.setByte("type", decoration.getType());
|
||||
decorationCompound.setByte("x", decoration.getX());
|
||||
decorationCompound.setByte("z", decoration.getZ());
|
||||
decorationCompound.setDouble("rot", decoration.getRotation());
|
||||
|
||||
decorationsList.add(decorationCompound);
|
||||
}
|
||||
compound.set("Decorations", decorationsList);
|
||||
}
|
||||
|
||||
{
|
||||
NBTCompound displayCompound;
|
||||
if (compound.containsKey("display")) {
|
||||
displayCompound = compound.getCompound("display");
|
||||
} else {
|
||||
displayCompound = new NBTCompound();
|
||||
}
|
||||
displayCompound.setInt("MapColor", mapColor.asRGB());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deepClone(@NotNull ItemMetaBuilder metaBuilder) {
|
||||
var mapBuilder = (MapMeta.Builder) metaBuilder;
|
||||
mapBuilder.mapId = mapId;
|
||||
mapBuilder.mapScaleDirection = mapScaleDirection;
|
||||
mapBuilder.decorations = decorations;
|
||||
mapBuilder.mapColor = mapColor;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull Supplier<@NotNull ItemMetaBuilder> getSupplier() {
|
||||
return Builder::new;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MapDecoration implements PublicCloneable<MapDecoration> {
|
||||
private final String id;
|
||||
private final byte type;
|
||||
private final byte x, z;
|
||||
private final double rotation;
|
||||
|
||||
public MapDecoration(@NotNull String id, byte type, byte x, byte z, double rotation) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the arbitrary decoration id.
|
||||
*
|
||||
* @return the decoration id
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the decoration type.
|
||||
*
|
||||
* @return the decoration type
|
||||
* @see <a href="https://minecraft.gamepedia.com/Map#Map_icons">Map icons</a>
|
||||
*/
|
||||
public byte getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the X position of the decoration.
|
||||
*
|
||||
* @return the X position
|
||||
*/
|
||||
public byte getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Z position of the decoration.
|
||||
*
|
||||
* @return the Z position
|
||||
*/
|
||||
public byte getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rotation of the symbol (0;360).
|
||||
*
|
||||
* @return the rotation of the symbol
|
||||
*/
|
||||
public double getRotation() {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public MapDecoration clone() {
|
||||
try {
|
||||
return (MapDecoration) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
MinecraftServer.getExceptionManager().handleException(e);
|
||||
throw new IllegalStateException("Something weird happened");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.item.ItemStack;
|
||||
import net.minestom.server.utils.clone.PublicCloneable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||
|
@ -1,10 +1,8 @@
|
||||
package net.minestom.server.item.metadata;
|
||||
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.chat.ChatColor;
|
||||
import net.minestom.server.color.Color;
|
||||
import net.minestom.server.color.DyeColor;
|
||||
import net.minestom.server.utils.clone.CloneUtils;
|
||||
import net.minestom.server.utils.clone.PublicCloneable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
Loading…
Reference in New Issue
Block a user