Inventory click listener

This commit is contained in:
TheMode 2019-08-14 06:50:03 +02:00
parent e2e7d67013
commit 60f5768011
7 changed files with 165 additions and 34 deletions

View File

@ -136,6 +136,7 @@ public class Player extends LivingEntity {
refreshOpenInventory(null); refreshOpenInventory(null);
} }
playerConnection.sendPacket(closeWindowPacket); playerConnection.sendPacket(closeWindowPacket);
inventory.update();
} }
public void refreshGameMode(GameMode gameMode) { public void refreshGameMode(GameMode gameMode) {

View File

@ -2,6 +2,7 @@ package fr.themode.minestom.inventory;
import fr.themode.minestom.entity.Player; import fr.themode.minestom.entity.Player;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
import fr.themode.minestom.net.packet.server.play.WindowItemsPacket; import fr.themode.minestom.net.packet.server.play.WindowItemsPacket;
import java.util.Arrays; import java.util.Arrays;
@ -11,7 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
public class Inventory implements InventoryClickHandler { public class Inventory implements InventoryModifier, InventoryClickHandler {
private static AtomicInteger lastInventoryId = new AtomicInteger(); private static AtomicInteger lastInventoryId = new AtomicInteger();
@ -52,6 +53,7 @@ public class Inventory implements InventoryClickHandler {
return id; return id;
} }
@Override
public void setItemStack(int slot, ItemStack itemStack) { public void setItemStack(int slot, ItemStack itemStack) {
if (slot < 0 || slot > inventoryType.getAdditionalSlot()) if (slot < 0 || slot > inventoryType.getAdditionalSlot())
throw new IllegalArgumentException(inventoryType.toString() + " does not have slot " + slot); throw new IllegalArgumentException(inventoryType.toString() + " does not have slot " + slot);
@ -59,6 +61,12 @@ public class Inventory implements InventoryClickHandler {
safeItemInsert(slot, itemStack); safeItemInsert(slot, itemStack);
} }
@Override
public boolean addItemStack(ItemStack itemStack) {
return false;
}
@Override
public ItemStack getItemStack(int slot) { public ItemStack getItemStack(int slot) {
return itemStacks[slot]; return itemStacks[slot];
} }
@ -88,7 +96,13 @@ public class Inventory implements InventoryClickHandler {
private void safeItemInsert(int slot, ItemStack itemStack) { private void safeItemInsert(int slot, ItemStack itemStack) {
synchronized (this) { synchronized (this) {
this.itemStacks[slot] = itemStack == null ? ItemStack.AIR_ITEM : itemStack; itemStack = itemStack == null ? ItemStack.AIR_ITEM : itemStack;
this.itemStacks[slot] = itemStack;
SetSlotPacket setSlotPacket = new SetSlotPacket();
setSlotPacket.windowId = 1;
setSlotPacket.slot = (short) slot;
setSlotPacket.itemStack = itemStack;
getViewers().forEach(player -> player.getPlayerConnection().sendPacket(setSlotPacket));
} }
} }
@ -125,9 +139,9 @@ public class Inventory implements InventoryClickHandler {
resultCursor = cursorItem.clone(); resultCursor = cursorItem.clone();
resultClicked = clicked.clone(); resultClicked = clicked.clone();
int amount = cursorItem.getAmount() + clicked.getAmount(); int amount = cursorItem.getAmount() + clicked.getAmount();
if (amount > 100) { if (amount > 64) {
resultCursor.setAmount((byte) (amount - 100)); resultCursor.setAmount((byte) (amount - 64));
resultClicked.setAmount((byte) 100); resultClicked.setAmount((byte) 64);
} else { } else {
resultCursor = ItemStack.AIR_ITEM; resultCursor = ItemStack.AIR_ITEM;
resultClicked.setAmount((byte) amount); resultClicked.setAmount((byte) amount);
@ -140,11 +154,11 @@ public class Inventory implements InventoryClickHandler {
if (isInWindow) { if (isInWindow) {
setItemStack(slot, resultClicked); setItemStack(slot, resultClicked);
setCursorPlayerItem(player, resultCursor); setCursorPlayerItem(player, resultCursor);
updateItems(); //updateItems();
} else { } else {
playerInventory.setItemStack(slot, offset, resultClicked); playerInventory.setItemStack(slot, offset, resultClicked);
setCursorPlayerItem(player, resultCursor); setCursorPlayerItem(player, resultCursor);
playerInventory.update(); //playerInventory.update();
} }
} }
@ -165,7 +179,7 @@ public class Inventory implements InventoryClickHandler {
resultCursor = cursorItem.clone(); resultCursor = cursorItem.clone();
resultClicked = clicked.clone(); resultClicked = clicked.clone();
int amount = clicked.getAmount() + 1; int amount = clicked.getAmount() + 1;
if (amount > 100) { if (amount > 64) {
return; return;
} else { } else {
resultCursor = cursorItem.clone(); resultCursor = cursorItem.clone();
@ -200,11 +214,9 @@ public class Inventory implements InventoryClickHandler {
if (isInWindow) { if (isInWindow) {
setItemStack(slot, resultClicked); setItemStack(slot, resultClicked);
setCursorPlayerItem(player, resultCursor); setCursorPlayerItem(player, resultCursor);
updateItems();
} else { } else {
playerInventory.setItemStack(slot, offset, resultClicked); playerInventory.setItemStack(slot, offset, resultClicked);
setCursorPlayerItem(player, resultCursor); setCursorPlayerItem(player, resultCursor);
playerInventory.update();
} }
} }
@ -215,7 +227,41 @@ public class Inventory implements InventoryClickHandler {
@Override @Override
public void changeHeld(Player player, int slot, int key) { public void changeHeld(Player player, int slot, int key) {
PlayerInventory playerInventory = player.getInventory();
if (!getCursorItem(player).isAir())
return;
boolean isInWindow = isClickInWindow(slot);
ItemStack heldItem = playerInventory.getItemStack(key);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack resultClicked;
ItemStack resultHeld;
if (clicked.isAir()) {
// Set held item [key] to slot
resultClicked = ItemStack.AIR_ITEM;
resultHeld = clicked.clone();
} else {
if (heldItem.isAir()) {
// if held item [key] is air then set clicked to held
resultClicked = ItemStack.AIR_ITEM;
resultHeld = clicked.clone();
} else {
System.out.println("CASE3");
// Otherwise replace held item and held
resultClicked = heldItem.clone();
resultHeld = clicked.clone();
}
}
if (isInWindow) {
setItemStack(slot, resultClicked);
} else {
playerInventory.setItemStack(slot, offset, resultClicked);
}
playerInventory.setItemStack(key, resultHeld);
} }
@Override @Override

View File

@ -0,0 +1,12 @@
package fr.themode.minestom.inventory;
import fr.themode.minestom.item.ItemStack;
public interface InventoryModifier {
void setItemStack(int slot, ItemStack itemStack);
boolean addItemStack(ItemStack itemStack);
ItemStack getItemStack(int slot);
}

View File

@ -2,15 +2,29 @@ package fr.themode.minestom.inventory;
import fr.themode.minestom.entity.Player; import fr.themode.minestom.entity.Player;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
import fr.themode.minestom.net.packet.server.play.WindowItemsPacket; import fr.themode.minestom.net.packet.server.play.WindowItemsPacket;
import fr.themode.minestom.net.player.PlayerConnection; import fr.themode.minestom.net.player.PlayerConnection;
import java.util.Arrays; import java.util.Arrays;
public class PlayerInventory { public class PlayerInventory implements InventoryModifier {
private static final int TOTAL_INVENTORY_SIZE = 46;
private static final int CRAFT_SLOT_1 = 36;
private static final int CRAFT_SLOT_2 = 37;
private static final int CRAFT_SLOT_3 = 38;
private static final int CRAFT_SLOT_4 = 39;
private static final int CRAFT_RESULT = 40;
private static final int HELMET_SLOT = 41;
private static final int CHESTPLATE_SLOT = 42;
private static final int LEGGINGS_SLOT = 43;
private static final int BOOTS_SLOT = 44;
private static final int OFFHAND_SLOT = 45;
private Player player; private Player player;
private ItemStack[] items = new ItemStack[45]; private ItemStack[] items = new ItemStack[TOTAL_INVENTORY_SIZE];
public PlayerInventory(Player player) { public PlayerInventory(Player player) {
this.player = player; this.player = player;
@ -18,28 +32,67 @@ public class PlayerInventory {
Arrays.fill(items, ItemStack.AIR_ITEM); Arrays.fill(items, ItemStack.AIR_ITEM);
} }
@Override
public ItemStack getItemStack(int slot) { public ItemStack getItemStack(int slot) {
return this.items[slot]; return this.items[slot];
} }
@Override
public void setItemStack(int slot, ItemStack itemStack) { public void setItemStack(int slot, ItemStack itemStack) {
safeItemInsert(slot, itemStack); safeItemInsert(slot, itemStack);
} }
@Override
public boolean addItemStack(ItemStack itemStack) {
synchronized (this) {
for (int i = 0; i < items.length - 10; i++) {
ItemStack item = items[i];
if (item.isAir()) {
setItemStack(i, itemStack);
return true;
} else if (itemStack.isSimilar(item)) {
// TODO check max stack size
int itemAmount = item.getAmount();
if (itemAmount == 64)
continue;
int totalAmount = itemStack.getAmount() + itemAmount;
if (totalAmount > 64) {
item.setAmount((byte) 64);
sendSlotRefresh((short) convertToPacketSlot(i), item);
itemStack.setAmount((byte) (totalAmount - 64));
} else {
item.setAmount((byte) totalAmount);
sendSlotRefresh((short) convertToPacketSlot(i), item);
return true;
}
}
}
}
return false;
}
public void setHelmet(ItemStack itemStack) { public void setHelmet(ItemStack itemStack) {
safeItemInsert(5, itemStack); safeItemInsert(HELMET_SLOT, itemStack);
} }
public void setChestplate(ItemStack itemStack) { public void setChestplate(ItemStack itemStack) {
safeItemInsert(6, itemStack); safeItemInsert(CHESTPLATE_SLOT, itemStack);
} }
public void setLeggings(ItemStack itemStack) { public void setLeggings(ItemStack itemStack) {
safeItemInsert(7, itemStack); safeItemInsert(LEGGINGS_SLOT, itemStack);
} }
public void setBoots(ItemStack itemStack) { public void setBoots(ItemStack itemStack) {
safeItemInsert(8, itemStack); safeItemInsert(BOOTS_SLOT, itemStack);
}
public void setItemInMainHand(ItemStack itemStack) {
safeItemInsert(player.getHeldSlot(), itemStack);
}
public void setItemInOffHand(ItemStack itemStack) {
safeItemInsert(OFFHAND_SLOT, itemStack);
} }
public void update() { public void update() {
@ -49,13 +102,15 @@ public class PlayerInventory {
private void safeItemInsert(int slot, ItemStack itemStack) { private void safeItemInsert(int slot, ItemStack itemStack) {
synchronized (this) { synchronized (this) {
this.items[slot] = itemStack == null ? ItemStack.AIR_ITEM : itemStack; itemStack = itemStack == null ? ItemStack.AIR_ITEM : itemStack;
this.items[slot] = itemStack;
System.out.println("INSERT: " + slot);
sendSlotRefresh((short) slot, itemStack);
} }
} }
protected void setItemStack(int slot, int offset, ItemStack itemStack) { protected void setItemStack(int slot, int offset, ItemStack itemStack) {
slot = convertSlot(slot, offset); slot = convertSlot(slot, offset);
// System.out.println("NEWSLOT: "+slot +" : "+itemStack.getItemId());
safeItemInsert(slot, itemStack); safeItemInsert(slot, itemStack);
} }
@ -64,6 +119,7 @@ public class PlayerInventory {
return this.items[slot]; return this.items[slot];
} }
protected int convertSlot(int slot, int offset) { protected int convertSlot(int slot, int offset) {
final int rowSize = 9; final int rowSize = 9;
slot -= offset; slot -= offset;
@ -72,27 +128,44 @@ public class PlayerInventory {
} else { } else {
slot = slot + rowSize; slot = slot + rowSize;
} }
System.out.println("DEBUG: " + slot);
return slot; return slot;
} }
private int convertToPacketSlot(int slot) {
if (slot > -1 && slot < 9) { // Held bar 0-9
slot = slot + 36;
} else if (slot > 8 && slot < 36) { // Inventory 9-35
slot = slot;
} else if (slot >= CRAFT_SLOT_1 && slot <= CRAFT_RESULT) { // Crafting 36-40
slot = slot - 36;
} else if (slot >= HELMET_SLOT && slot <= BOOTS_SLOT) { // Armor 41-44
slot = slot - 36;
} else if (slot == OFFHAND_SLOT) { // Off hand
slot = 45;
}
return slot;
}
private void sendSlotRefresh(short slot, ItemStack itemStack) {
SetSlotPacket setSlotPacket = new SetSlotPacket();
setSlotPacket.windowId = (byte) (slot > 35 && slot < TOTAL_INVENTORY_SIZE ? 0 : -2);
setSlotPacket.slot = slot;
setSlotPacket.itemStack = itemStack;
player.getPlayerConnection().sendPacket(setSlotPacket);
}
private WindowItemsPacket createWindowItemsPacket() { private WindowItemsPacket createWindowItemsPacket() {
ItemStack[] convertedSlots = new ItemStack[45]; ItemStack[] convertedSlots = new ItemStack[TOTAL_INVENTORY_SIZE];
Arrays.fill(convertedSlots, ItemStack.AIR_ITEM); // TODO armor and craft Arrays.fill(convertedSlots, ItemStack.AIR_ITEM); // TODO armor and craft
// Hotbar for (int i = 0; i < items.length; i++) {
for (int i = 0; i < 9; i++) { int slot = convertToPacketSlot(i);
convertedSlots[36 + i] = items[i]; convertedSlots[slot] = items[i];
}
// Inventory
for (int i = 10; i < 9 + 9 * 3; i++) {
convertedSlots[i] = items[i];
} }
WindowItemsPacket windowItemsPacket = new WindowItemsPacket(); WindowItemsPacket windowItemsPacket = new WindowItemsPacket();
windowItemsPacket.windowId = 0; windowItemsPacket.windowId = 0;
windowItemsPacket.count = 45; windowItemsPacket.count = TOTAL_INVENTORY_SIZE;
windowItemsPacket.items = convertedSlots; windowItemsPacket.items = convertedSlots;
return windowItemsPacket; return windowItemsPacket;
} }

View File

@ -1,6 +1,6 @@
package fr.themode.minestom.item; package fr.themode.minestom.item;
public class ItemStack implements Cloneable { public class ItemStack {
public static final ItemStack AIR_ITEM = new ItemStack(0, (byte) 1); public static final ItemStack AIR_ITEM = new ItemStack(0, (byte) 1);

View File

@ -143,9 +143,8 @@ public class LoginStartPacket implements ClientPreplayPacket {
//System.out.println("HAHAHAHHAHHAH " + player.getUuid()); //System.out.println("HAHAHAHHAHHAH " + player.getUuid());
PlayerInventory inventory = player.getInventory(); PlayerInventory inventory = player.getInventory();
inventory.setItemStack(1, new ItemStack(1, (byte) 32)); inventory.addItemStack(new ItemStack(1, (byte) 60));
inventory.setItemStack(2, new ItemStack(1, (byte) 32)); inventory.addItemStack(new ItemStack(1, (byte) 50));
inventory.update();
Inventory inv = new Inventory(InventoryType.WINDOW_3X3, "Salut je suis le titre"); Inventory inv = new Inventory(InventoryType.WINDOW_3X3, "Salut je suis le titre");
inv.setItemStack(0, new ItemStack(1, (byte) 1)); inv.setItemStack(0, new ItemStack(1, (byte) 1));

View File

@ -52,7 +52,7 @@ public class ClientClickWindowPacket implements ClientPlayPacket {
} }
break; break;
case 2: case 2:
// Number key 1-9 inventory.changeHeld(player, slot, button);
break; break;
case 3: case 3:
// Middle click (only creative players in non-player inventories) // Middle click (only creative players in non-player inventories)