mirror of
https://github.com/Minestom/Minestom.git
synced 2025-04-12 15:15:47 +02: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.entity.type.decoration.EntityItemFrame;
|
||||||
import net.minestom.server.instance.Instance;
|
import net.minestom.server.instance.Instance;
|
||||||
import net.minestom.server.instance.InstanceManager;
|
import net.minestom.server.instance.InstanceManager;
|
||||||
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.item.Material;
|
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.Framebuffer;
|
||||||
import net.minestom.server.map.LargeFramebuffer;
|
import net.minestom.server.map.LargeFramebuffer;
|
||||||
import net.minestom.server.map.MapColors;
|
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) {
|
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);
|
EntityItemFrame itemFrame = new EntityItemFrame(new Position(x, y, z), EntityItemFrame.ItemFrameOrientation.NORTH);
|
||||||
itemFrame.getPosition().setYaw(180f);
|
itemFrame.getPosition().setYaw(180f);
|
||||||
ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1);
|
ItemStack map = ItemStack.builder(Material.FILLED_MAP)
|
||||||
map.setItemMeta(new MapMeta(id));
|
.meta(new MapMeta.Builder().mapId(id).build())
|
||||||
|
.build();
|
||||||
itemFrame.setItemStack(map);
|
itemFrame.setItemStack(map);
|
||||||
itemFrame.setInstance(instance);
|
itemFrame.setInstance(instance);
|
||||||
itemFrame.setCustomNameVisible(true);
|
itemFrame.setCustomNameVisible(true);
|
||||||
|
@ -4,7 +4,7 @@ import net.minestom.server.entity.Entity;
|
|||||||
import net.minestom.server.entity.Player;
|
import net.minestom.server.entity.Player;
|
||||||
import net.minestom.server.instance.block.BlockFace;
|
import net.minestom.server.instance.block.BlockFace;
|
||||||
import net.minestom.server.inventory.Inventory;
|
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.inventory.PlayerInventory;
|
||||||
import net.minestom.server.item.ItemStack;
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.network.packet.client.ClientPlayPacket;
|
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) {
|
public void clickWindow(boolean playerInventory, short slot, byte button, short action, int mode) {
|
||||||
Inventory inventory = playerInventory ? null : fakePlayer.getOpenInventory();
|
Inventory inventory = playerInventory ? null : fakePlayer.getOpenInventory();
|
||||||
InventoryModifier inventoryModifier = inventory == null ? fakePlayer.getInventory() : inventory;
|
AbstractInventory abstractInventory = inventory == null ? fakePlayer.getInventory() : inventory;
|
||||||
playerInventory = inventoryModifier instanceof PlayerInventory;
|
playerInventory = abstractInventory instanceof PlayerInventory;
|
||||||
|
|
||||||
slot = playerInventory ? (short) PlayerInventoryUtils.convertToPacketSlot(slot) : slot;
|
slot = playerInventory ? (short) PlayerInventoryUtils.convertToPacketSlot(slot) : slot;
|
||||||
|
|
||||||
ItemStack itemStack = inventoryModifier.getItemStack(slot);
|
ItemStack itemStack = abstractInventory.getItemStack(slot);
|
||||||
|
|
||||||
ClientClickWindowPacket clickWindowPacket = new ClientClickWindowPacket();
|
ClientClickWindowPacket clickWindowPacket = new ClientClickWindowPacket();
|
||||||
clickWindowPacket.windowId = playerInventory ? 0 : inventory.getWindowId();
|
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.
|
* 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)}.
|
* 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)
|
// incremented each time an inventory is created (used in the window packets)
|
||||||
private static final AtomicInteger LAST_INVENTORY_ID = new AtomicInteger();
|
private static final AtomicInteger LAST_INVENTORY_ID = new AtomicInteger();
|
||||||
@ -150,19 +150,13 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
|||||||
@Override
|
@Override
|
||||||
public synchronized boolean addItemStack(@NotNull ItemStack itemStack) {
|
public synchronized boolean addItemStack(@NotNull ItemStack itemStack) {
|
||||||
// Make the method synchronized
|
// Make the method synchronized
|
||||||
return InventoryModifier.super.addItemStack(itemStack);
|
return 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
public synchronized void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
||||||
// Make the method synchronized
|
// Make the method synchronized
|
||||||
InventoryModifier.super.replaceItemStack(slot, operator);
|
super.replaceItemStack(slot, operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -299,7 +293,8 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
|
|||||||
* @param slot the internal slot id
|
* @param slot the internal slot id
|
||||||
* @param itemStack the item to insert
|
* @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;
|
this.itemStacks[slot] = itemStack;
|
||||||
SetSlotPacket setSlotPacket = new SetSlotPacket();
|
SetSlotPacket setSlotPacket = new SetSlotPacket();
|
||||||
setSlotPacket.windowId = getWindowId();
|
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()}.
|
* 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 INVENTORY_SIZE = 46;
|
||||||
|
public static final int INNER_INVENTORY_SIZE = 36;
|
||||||
|
|
||||||
protected final Player player;
|
protected final Player player;
|
||||||
protected final ItemStack[] itemStacks = new ItemStack[INVENTORY_SIZE];
|
protected final ItemStack[] itemStacks = new ItemStack[INVENTORY_SIZE];
|
||||||
@ -93,24 +94,13 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
itemStack = addItemStackEvent.getItemStack();
|
itemStack = addItemStackEvent.getItemStack();
|
||||||
return InventoryModifier.super.addItemStack(itemStack, 0, getSize() - 10);
|
return super.addItemStack(itemStack);
|
||||||
}
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
public synchronized void replaceItemStack(int slot, @NotNull UnaryOperator<@NotNull ItemStack> operator) {
|
||||||
// Make the method synchronized
|
// Make the method synchronized
|
||||||
InventoryModifier.super.replaceItemStack(slot, operator);
|
super.replaceItemStack(slot, operator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -130,6 +120,11 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
|
|||||||
return INVENTORY_SIZE;
|
return INVENTORY_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getInnerSize() {
|
||||||
|
return INNER_INVENTORY_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemInMainHand() {
|
public ItemStack getItemInMainHand() {
|
||||||
@ -237,6 +232,7 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
|
|||||||
* @throws IllegalArgumentException if the slot {@code slot} does not exist
|
* @throws IllegalArgumentException if the slot {@code slot} does not exist
|
||||||
* @throws NullPointerException if {@code itemStack} is null
|
* @throws NullPointerException if {@code itemStack} is null
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
protected synchronized void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
|
protected synchronized void safeItemInsert(int slot, @NotNull ItemStack itemStack) {
|
||||||
Check.argCondition(!MathUtils.isBetween(slot, 0, getSize()),
|
Check.argCondition(!MathUtils.isBetween(slot, 0, getSize()),
|
||||||
"The slot " + slot + " does not exist for player");
|
"The slot " + slot + " does not exist for player");
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package net.minestom.server.inventory.condition;
|
package net.minestom.server.inventory.condition;
|
||||||
|
|
||||||
import net.minestom.server.entity.Player;
|
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;
|
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)}
|
* using {@link net.minestom.server.inventory.Inventory#addInventoryCondition(InventoryCondition)}
|
||||||
* or {@link net.minestom.server.inventory.PlayerInventory#addInventoryCondition(InventoryCondition)}
|
* or {@link net.minestom.server.inventory.PlayerInventory#addInventoryCondition(InventoryCondition)}
|
||||||
* in order to listen to any issued clicks.
|
* 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;
|
package net.minestom.server.item.metadata;
|
||||||
|
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
|
import net.minestom.server.item.ItemStack;
|
||||||
import net.minestom.server.utils.clone.PublicCloneable;
|
import net.minestom.server.utils.clone.PublicCloneable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package net.minestom.server.item.metadata;
|
package net.minestom.server.item.metadata;
|
||||||
|
|
||||||
import net.kyori.adventure.text.format.TextColor;
|
|
||||||
import net.minestom.server.MinecraftServer;
|
import net.minestom.server.MinecraftServer;
|
||||||
import net.minestom.server.chat.ChatColor;
|
import net.minestom.server.chat.ChatColor;
|
||||||
import net.minestom.server.color.Color;
|
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.CloneUtils;
|
||||||
import net.minestom.server.utils.clone.PublicCloneable;
|
import net.minestom.server.utils.clone.PublicCloneable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
Loading…
Reference in New Issue
Block a user