mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-13 11:41:52 +01:00
Enhanced inventory creation & listener
This commit is contained in:
parent
349de8773f
commit
e2e7d67013
@ -1,6 +1,7 @@
|
||||
package fr.themode.minestom.entity;
|
||||
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.inventory.Inventory;
|
||||
import fr.themode.minestom.inventory.PlayerInventory;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.packet.server.play.*;
|
||||
@ -21,6 +22,7 @@ public class Player extends LivingEntity {
|
||||
private GameMode gameMode;
|
||||
private PlayerInventory inventory;
|
||||
private short heldSlot;
|
||||
private Inventory openInventory;
|
||||
|
||||
// TODO set proper UUID
|
||||
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
||||
@ -102,6 +104,40 @@ public class Player extends LivingEntity {
|
||||
return inventory.getItemStack(heldSlot);
|
||||
}
|
||||
|
||||
public Inventory getOpenInventory() {
|
||||
return openInventory;
|
||||
}
|
||||
|
||||
public void openInventory(Inventory inventory) {
|
||||
if (inventory == null)
|
||||
throw new IllegalArgumentException("Inventory cannot be null, use Player#closeInventory() to close current");
|
||||
|
||||
if (getOpenInventory() != null) {
|
||||
getOpenInventory().removeViewer(this);
|
||||
}
|
||||
|
||||
OpenWindowPacket openWindowPacket = new OpenWindowPacket();
|
||||
openWindowPacket.windowId = inventory.getUniqueId();
|
||||
openWindowPacket.windowType = inventory.getInventoryType().getWindowType();
|
||||
openWindowPacket.title = inventory.getTitle();
|
||||
playerConnection.sendPacket(openWindowPacket);
|
||||
inventory.addViewer(this);
|
||||
refreshOpenInventory(inventory);
|
||||
}
|
||||
|
||||
public void closeInventory() {
|
||||
Inventory openInventory = getOpenInventory();
|
||||
CloseWindowPacket closeWindowPacket = new CloseWindowPacket();
|
||||
if (openInventory == null) {
|
||||
closeWindowPacket.windowId = 0;
|
||||
} else {
|
||||
closeWindowPacket.windowId = openInventory.getUniqueId();
|
||||
openInventory.removeViewer(this);
|
||||
refreshOpenInventory(null);
|
||||
}
|
||||
playerConnection.sendPacket(closeWindowPacket);
|
||||
}
|
||||
|
||||
public void refreshGameMode(GameMode gameMode) {
|
||||
this.gameMode = gameMode;
|
||||
}
|
||||
@ -131,6 +167,10 @@ public class Player extends LivingEntity {
|
||||
this.heldSlot = slot;
|
||||
}
|
||||
|
||||
public void refreshOpenInventory(Inventory openInventory) {
|
||||
this.openInventory = openInventory;
|
||||
}
|
||||
|
||||
public long getLastKeepAlive() {
|
||||
return lastKeepAlive;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class BlockBatch {
|
||||
for (BlockData data : dataList) {
|
||||
data.apply(chunk);
|
||||
}
|
||||
instance.sendChunkUpdate(chunk);
|
||||
instance.sendChunkUpdate(chunk); // TODO partial chunk data
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@ public class BlockBatch {
|
||||
private Block block;
|
||||
|
||||
public void apply(Chunk chunk) {
|
||||
chunk.setBlock(x % 16, y, z % 16, block);
|
||||
chunk.setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class Chunk {
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
public void setBlock(int x, int y, int z, Block block) {
|
||||
protected void setBlock(int x, int y, int z, Block block) {
|
||||
short index = (short) (x & 0x000F);
|
||||
index |= (y << 4) & 0x0FF0;
|
||||
index |= (z << 12) & 0xF000;
|
||||
|
235
src/main/java/fr/themode/minestom/inventory/Inventory.java
Normal file
235
src/main/java/fr/themode/minestom/inventory/Inventory.java
Normal file
@ -0,0 +1,235 @@
|
||||
package fr.themode.minestom.inventory;
|
||||
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.packet.server.play.WindowItemsPacket;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class Inventory implements InventoryClickHandler {
|
||||
|
||||
private static AtomicInteger lastInventoryId = new AtomicInteger();
|
||||
|
||||
private int id;
|
||||
private InventoryType inventoryType;
|
||||
private String title;
|
||||
|
||||
private int offset;
|
||||
|
||||
private ItemStack[] itemStacks;
|
||||
private Set<Player> viewers = new CopyOnWriteArraySet<>();
|
||||
private ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
|
||||
|
||||
public Inventory(InventoryType inventoryType, String title) {
|
||||
this.id = generateId();
|
||||
this.inventoryType = inventoryType;
|
||||
this.title = title;
|
||||
|
||||
this.offset = inventoryType.getAdditionalSlot();
|
||||
|
||||
this.itemStacks = new ItemStack[inventoryType.getAdditionalSlot()];
|
||||
Arrays.fill(itemStacks, ItemStack.AIR_ITEM);
|
||||
}
|
||||
|
||||
private static int generateId() {
|
||||
return lastInventoryId.incrementAndGet();
|
||||
}
|
||||
|
||||
public InventoryType getInventoryType() {
|
||||
return inventoryType;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public int getUniqueId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setItemStack(int slot, ItemStack itemStack) {
|
||||
if (slot < 0 || slot > inventoryType.getAdditionalSlot())
|
||||
throw new IllegalArgumentException(inventoryType.toString() + " does not have slot " + slot);
|
||||
|
||||
safeItemInsert(slot, itemStack);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(int slot) {
|
||||
return itemStacks[slot];
|
||||
}
|
||||
|
||||
public void updateItems() {
|
||||
WindowItemsPacket windowItemsPacket = getWindowItemsPacket();
|
||||
getViewers().forEach(p -> p.getPlayerConnection().sendPacket(windowItemsPacket));
|
||||
}
|
||||
|
||||
public Set<Player> getViewers() {
|
||||
return Collections.unmodifiableSet(viewers);
|
||||
}
|
||||
|
||||
public void addViewer(Player player) {
|
||||
this.viewers.add(player);
|
||||
WindowItemsPacket windowItemsPacket = getWindowItemsPacket();
|
||||
player.getPlayerConnection().sendPacket(windowItemsPacket);
|
||||
}
|
||||
|
||||
public void removeViewer(Player player) {
|
||||
this.viewers.remove(player);
|
||||
}
|
||||
|
||||
public ItemStack getCursorItem(Player player) {
|
||||
return cursorPlayersItem.getOrDefault(player, ItemStack.AIR_ITEM);
|
||||
}
|
||||
|
||||
private void safeItemInsert(int slot, ItemStack itemStack) {
|
||||
synchronized (this) {
|
||||
this.itemStacks[slot] = itemStack == null ? ItemStack.AIR_ITEM : itemStack;
|
||||
}
|
||||
}
|
||||
|
||||
private WindowItemsPacket getWindowItemsPacket() {
|
||||
WindowItemsPacket windowItemsPacket = new WindowItemsPacket();
|
||||
windowItemsPacket.windowId = getUniqueId();
|
||||
windowItemsPacket.count = (short) itemStacks.length;
|
||||
windowItemsPacket.items = itemStacks;
|
||||
return windowItemsPacket;
|
||||
}
|
||||
|
||||
private void setCursorPlayerItem(Player player, ItemStack itemStack) {
|
||||
this.cursorPlayersItem.put(player, itemStack);
|
||||
}
|
||||
|
||||
private boolean isClickInWindow(int slot) {
|
||||
return slot < inventoryType.getAdditionalSlot();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void leftClick(Player player, int slot) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack cursorItem = getCursorItem(player);
|
||||
boolean isInWindow = isClickInWindow(slot);
|
||||
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
|
||||
|
||||
if (cursorItem.isAir() && clicked.isAir())
|
||||
return;
|
||||
|
||||
ItemStack resultCursor;
|
||||
ItemStack resultClicked;
|
||||
|
||||
if (cursorItem.isSimilar(clicked)) {
|
||||
resultCursor = cursorItem.clone();
|
||||
resultClicked = clicked.clone();
|
||||
int amount = cursorItem.getAmount() + clicked.getAmount();
|
||||
if (amount > 100) {
|
||||
resultCursor.setAmount((byte) (amount - 100));
|
||||
resultClicked.setAmount((byte) 100);
|
||||
} else {
|
||||
resultCursor = ItemStack.AIR_ITEM;
|
||||
resultClicked.setAmount((byte) amount);
|
||||
}
|
||||
} else {
|
||||
resultCursor = clicked.clone();
|
||||
resultClicked = cursorItem.clone();
|
||||
}
|
||||
|
||||
if (isInWindow) {
|
||||
setItemStack(slot, resultClicked);
|
||||
setCursorPlayerItem(player, resultCursor);
|
||||
updateItems();
|
||||
} else {
|
||||
playerInventory.setItemStack(slot, offset, resultClicked);
|
||||
setCursorPlayerItem(player, resultCursor);
|
||||
playerInventory.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rightClick(Player player, int slot) {
|
||||
PlayerInventory playerInventory = player.getInventory();
|
||||
ItemStack cursorItem = getCursorItem(player);
|
||||
boolean isInWindow = isClickInWindow(slot);
|
||||
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
|
||||
|
||||
if (cursorItem.isAir() && clicked.isAir())
|
||||
return;
|
||||
|
||||
ItemStack resultCursor;
|
||||
ItemStack resultClicked;
|
||||
|
||||
if (cursorItem.isSimilar(clicked)) {
|
||||
resultCursor = cursorItem.clone();
|
||||
resultClicked = clicked.clone();
|
||||
int amount = clicked.getAmount() + 1;
|
||||
if (amount > 100) {
|
||||
return;
|
||||
} else {
|
||||
resultCursor = cursorItem.clone();
|
||||
resultCursor.setAmount((byte) (resultCursor.getAmount() - 1));
|
||||
if (resultCursor.getAmount() < 1)
|
||||
resultCursor = ItemStack.AIR_ITEM;
|
||||
resultClicked.setAmount((byte) amount);
|
||||
}
|
||||
} else {
|
||||
if (cursorItem.isAir()) {
|
||||
int amount = (int) Math.ceil((double) clicked.getAmount() / 2d);
|
||||
resultCursor = clicked.clone();
|
||||
resultCursor.setAmount((byte) amount);
|
||||
resultClicked = clicked.clone();
|
||||
resultClicked.setAmount((byte) (clicked.getAmount() / 2));
|
||||
} else {
|
||||
if (clicked.isAir()) {
|
||||
int amount = cursorItem.getAmount();
|
||||
resultCursor = cursorItem.clone();
|
||||
resultCursor.setAmount((byte) (amount - 1));
|
||||
if (resultCursor.getAmount() < 1)
|
||||
resultCursor = ItemStack.AIR_ITEM;
|
||||
resultClicked = cursorItem.clone();
|
||||
resultClicked.setAmount((byte) 1);
|
||||
} else {
|
||||
resultCursor = clicked.clone();
|
||||
resultClicked = cursorItem.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isInWindow) {
|
||||
setItemStack(slot, resultClicked);
|
||||
setCursorPlayerItem(player, resultCursor);
|
||||
updateItems();
|
||||
} else {
|
||||
playerInventory.setItemStack(slot, offset, resultClicked);
|
||||
setCursorPlayerItem(player, resultCursor);
|
||||
playerInventory.update();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shiftClick(Player player, int slot) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeHeld(Player player, int slot, int key) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void middleClick(Player player, int slot) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropOne(Player player, int slot) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dropItemStack(Player player, int slot) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package fr.themode.minestom.inventory;
|
||||
|
||||
import fr.themode.minestom.entity.Player;
|
||||
|
||||
public interface InventoryClickHandler {
|
||||
|
||||
void leftClick(Player player, int slot);
|
||||
|
||||
void rightClick(Player player, int slot);
|
||||
|
||||
void shiftClick(Player player, int slot); // shift + left/right click have the same behavior
|
||||
|
||||
void changeHeld(Player player, int slot, int key);
|
||||
|
||||
void middleClick(Player player, int slot);
|
||||
|
||||
void dropOne(Player player, int slot);
|
||||
|
||||
void dropItemStack(Player player, int slot);
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package fr.themode.minestom.inventory;
|
||||
|
||||
public enum InventoryType {
|
||||
|
||||
CHEST_1_ROW(0, 9),
|
||||
CHEST_2_ROW(1, 18),
|
||||
CHEST_3_ROW(2, 27),
|
||||
CHEST_4_ROW(3, 36),
|
||||
CHEST_5_ROW(4, 45),
|
||||
CHEST_6_ROW(5, 54),
|
||||
WINDOW_3X3(6, 9),
|
||||
ANVIL(7, 3),
|
||||
BEACON(8, 1),
|
||||
BLAST_FURNACE(9, 3),
|
||||
BREWING_STAND(10, 5),
|
||||
CRAFTING(11, 10),
|
||||
ENCHANTMENT(12, 2),
|
||||
FURNACE(13, 3),
|
||||
GRINDSTONE(14, 3),
|
||||
HOPPER(15, 5),
|
||||
LECTERN(16, 0),
|
||||
LOOM(17, 4),
|
||||
MERCHANT(18, 3),
|
||||
SHULKER_BOX(19, 27),
|
||||
SMOKER(20, 3),
|
||||
CARTOGRAPHY(21, 3),
|
||||
STONE_CUTTER(22, 2);
|
||||
|
||||
private int windowType;
|
||||
private int slot;
|
||||
|
||||
InventoryType(int windowType, int slot) {
|
||||
this.windowType = windowType;
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
public int getWindowType() {
|
||||
return windowType;
|
||||
}
|
||||
|
||||
public int getAdditionalSlot() {
|
||||
return slot;
|
||||
}
|
||||
|
||||
}
|
@ -5,6 +5,8 @@ import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.packet.server.play.WindowItemsPacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PlayerInventory {
|
||||
|
||||
private Player player;
|
||||
@ -12,51 +14,87 @@ public class PlayerInventory {
|
||||
|
||||
public PlayerInventory(Player player) {
|
||||
this.player = player;
|
||||
|
||||
Arrays.fill(items, ItemStack.AIR_ITEM);
|
||||
}
|
||||
|
||||
public ItemStack getItemStack(int slot) {
|
||||
ItemStack item = this.items[convertSlot(slot)];
|
||||
return item != null ? item : ItemStack.AIR_ITEM;
|
||||
return this.items[slot];
|
||||
}
|
||||
|
||||
public void setItemStack(int slot, ItemStack itemStack) {
|
||||
this.items[convertSlot(slot)] = itemStack;
|
||||
safeItemInsert(slot, itemStack);
|
||||
}
|
||||
|
||||
public void setHelmet(ItemStack itemStack) {
|
||||
this.items[5] = itemStack;
|
||||
safeItemInsert(5, itemStack);
|
||||
}
|
||||
|
||||
public void setChestplate(ItemStack itemStack) {
|
||||
this.items[6] = itemStack;
|
||||
safeItemInsert(6, itemStack);
|
||||
}
|
||||
|
||||
public void setLeggings(ItemStack itemStack) {
|
||||
this.items[7] = itemStack;
|
||||
safeItemInsert(7, itemStack);
|
||||
}
|
||||
|
||||
public void setBoots(ItemStack itemStack) {
|
||||
this.items[8] = itemStack;
|
||||
safeItemInsert(8, itemStack);
|
||||
}
|
||||
|
||||
public void update() {
|
||||
PlayerConnection playerConnection = player.getPlayerConnection();
|
||||
|
||||
WindowItemsPacket windowItemsPacket = new WindowItemsPacket();
|
||||
windowItemsPacket.windowId = 0; // player inventory ID
|
||||
windowItemsPacket.count = (short) items.length;
|
||||
windowItemsPacket.items = items;
|
||||
playerConnection.sendPacket(windowItemsPacket);
|
||||
playerConnection.sendPacket(createWindowItemsPacket());
|
||||
}
|
||||
|
||||
private int convertSlot(int slot) {
|
||||
if (slot >= 0 && slot <= 9 * 4) {
|
||||
int row = slot / 9;
|
||||
int place = slot % 9;
|
||||
int converted = 9 * (4 - 1 - row) + place + 9;
|
||||
return converted;
|
||||
private void safeItemInsert(int slot, ItemStack itemStack) {
|
||||
synchronized (this) {
|
||||
this.items[slot] = itemStack == null ? ItemStack.AIR_ITEM : itemStack;
|
||||
}
|
||||
}
|
||||
|
||||
protected void setItemStack(int slot, int offset, ItemStack itemStack) {
|
||||
slot = convertSlot(slot, offset);
|
||||
// System.out.println("NEWSLOT: "+slot +" : "+itemStack.getItemId());
|
||||
safeItemInsert(slot, itemStack);
|
||||
}
|
||||
|
||||
protected ItemStack getItemStack(int slot, int offset) {
|
||||
slot = convertSlot(slot, offset);
|
||||
return this.items[slot];
|
||||
}
|
||||
|
||||
protected int convertSlot(int slot, int offset) {
|
||||
final int rowSize = 9;
|
||||
slot -= offset;
|
||||
if (slot >= rowSize * 3 && slot < rowSize * 4) {
|
||||
slot = slot % 9;
|
||||
} else {
|
||||
slot = slot + rowSize;
|
||||
}
|
||||
System.out.println("DEBUG: " + slot);
|
||||
return slot;
|
||||
}
|
||||
|
||||
private WindowItemsPacket createWindowItemsPacket() {
|
||||
ItemStack[] convertedSlots = new ItemStack[45];
|
||||
Arrays.fill(convertedSlots, ItemStack.AIR_ITEM); // TODO armor and craft
|
||||
|
||||
// Hotbar
|
||||
for (int i = 0; i < 9; i++) {
|
||||
convertedSlots[36 + i] = items[i];
|
||||
}
|
||||
|
||||
// Inventory
|
||||
for (int i = 10; i < 9 + 9 * 3; i++) {
|
||||
convertedSlots[i] = items[i];
|
||||
}
|
||||
|
||||
WindowItemsPacket windowItemsPacket = new WindowItemsPacket();
|
||||
windowItemsPacket.windowId = 0;
|
||||
windowItemsPacket.count = 45;
|
||||
windowItemsPacket.items = convertedSlots;
|
||||
return windowItemsPacket;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,22 +1,38 @@
|
||||
package fr.themode.minestom.item;
|
||||
|
||||
public class ItemStack {
|
||||
public class ItemStack implements Cloneable {
|
||||
|
||||
public static final ItemStack AIR_ITEM = new ItemStack(0, (byte) 1);
|
||||
|
||||
private int itemId;
|
||||
private byte count;
|
||||
private byte amount;
|
||||
|
||||
public ItemStack(int itemId, byte count) {
|
||||
public ItemStack(int itemId, byte amount) {
|
||||
this.itemId = itemId;
|
||||
this.count = count;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public boolean isAir() {
|
||||
return itemId == 0;
|
||||
}
|
||||
|
||||
public boolean isSimilar(ItemStack itemStack) {
|
||||
return itemStack.getItemId() == itemId;
|
||||
}
|
||||
|
||||
public byte getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
public byte getCount() {
|
||||
return count;
|
||||
public void setAmount(byte amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public ItemStack clone() {
|
||||
return new ItemStack(itemId, amount);
|
||||
}
|
||||
}
|
||||
|
@ -21,5 +21,8 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler {
|
||||
register(0x1A, ClientPlayerDiggingPacket.class);
|
||||
register(0x2C, ClientPlayerBlockPlacementPacket.class);
|
||||
register(0x23, ClientHeldItemChangePacket.class);
|
||||
register(0x09, ClientClickWindowPacket.class);
|
||||
register(0x0A, ClientCloseWindow.class);
|
||||
register(0x07, ClientConfirmTransactionPacket.class);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.entity.demo.ChickenCreature;
|
||||
import fr.themode.minestom.instance.Block;
|
||||
import fr.themode.minestom.instance.Instance;
|
||||
import fr.themode.minestom.inventory.Inventory;
|
||||
import fr.themode.minestom.inventory.InventoryType;
|
||||
import fr.themode.minestom.inventory.PlayerInventory;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.ConnectionManager;
|
||||
@ -56,7 +58,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
||||
connection.setConnectionState(ConnectionState.PLAY);
|
||||
connectionManager.createPlayer(uuids.get(username), username, connection);
|
||||
Player player = connectionManager.getPlayer(connection);
|
||||
GameMode gameMode = GameMode.CREATIVE;
|
||||
GameMode gameMode = GameMode.SURVIVAL;
|
||||
|
||||
player.refreshGameMode(gameMode);
|
||||
|
||||
@ -141,9 +143,16 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
||||
//System.out.println("HAHAHAHHAHHAH " + player.getUuid());
|
||||
|
||||
PlayerInventory inventory = player.getInventory();
|
||||
inventory.setItemStack(1, new ItemStack(1, (byte) 1));
|
||||
inventory.setItemStack(1, new ItemStack(1, (byte) 32));
|
||||
inventory.setItemStack(2, new ItemStack(1, (byte) 32));
|
||||
inventory.update();
|
||||
|
||||
Inventory inv = new Inventory(InventoryType.WINDOW_3X3, "Salut je suis le titre");
|
||||
inv.setItemStack(0, new ItemStack(1, (byte) 1));
|
||||
player.openInventory(inv);
|
||||
inv.setItemStack(1, new ItemStack(1, (byte) 2));
|
||||
inv.updateItems();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,90 @@
|
||||
package fr.themode.minestom.net.packet.client.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.inventory.Inventory;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.ConfirmTransactionPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class ClientClickWindowPacket implements ClientPlayPacket {
|
||||
|
||||
public byte windowId;
|
||||
public short slot;
|
||||
public byte button;
|
||||
public short actionNumber;
|
||||
public int mode;
|
||||
// TODO clicked item
|
||||
|
||||
@Override
|
||||
public void process(Player player) {
|
||||
Inventory inventory = player.getOpenInventory();
|
||||
System.out.println("Window id: " + windowId + " | slot: " + slot + " | button: " + button + " | mode: " + mode);
|
||||
|
||||
ConfirmTransactionPacket confirmTransactionPacket = new ConfirmTransactionPacket();
|
||||
confirmTransactionPacket.windowId = windowId;
|
||||
confirmTransactionPacket.actionNumber = actionNumber;
|
||||
confirmTransactionPacket.accepted = true; // Change depending on output
|
||||
|
||||
switch (mode) {
|
||||
case 0:
|
||||
switch (button) {
|
||||
case 0:
|
||||
// Left click
|
||||
inventory.leftClick(player, slot);
|
||||
break;
|
||||
case 1:
|
||||
// Right click
|
||||
inventory.rightClick(player, slot);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
switch (button) {
|
||||
case 0:
|
||||
// Shift + left click
|
||||
break;
|
||||
case 1:
|
||||
// Shift + right click
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Number key 1-9
|
||||
break;
|
||||
case 3:
|
||||
// Middle click (only creative players in non-player inventories)
|
||||
break;
|
||||
case 4:
|
||||
// Dropping functions
|
||||
break;
|
||||
case 5:
|
||||
// Dragging
|
||||
break;
|
||||
case 6:
|
||||
// Double click (merge similar items)
|
||||
break;
|
||||
}
|
||||
|
||||
ItemStack cursorItem = inventory.getCursorItem(player);
|
||||
SetSlotPacket setSlotPacket = new SetSlotPacket();
|
||||
setSlotPacket.windowId = -1;
|
||||
setSlotPacket.slot = -1;
|
||||
setSlotPacket.itemStack = cursorItem;
|
||||
|
||||
player.getPlayerConnection().sendPacket(setSlotPacket);
|
||||
player.getPlayerConnection().sendPacket(confirmTransactionPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Buffer buffer) {
|
||||
this.windowId = buffer.getByte();
|
||||
this.slot = buffer.getShort();
|
||||
this.button = buffer.getByte();
|
||||
this.actionNumber = buffer.getShort();
|
||||
this.mode = Utils.readVarInt(buffer);
|
||||
// TODO read clicked item
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package fr.themode.minestom.net.packet.client.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.inventory.Inventory;
|
||||
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class ClientCloseWindow implements ClientPlayPacket {
|
||||
|
||||
public int windowId;
|
||||
|
||||
@Override
|
||||
public void process(Player player) {
|
||||
System.out.println("CLOSED: " + windowId);
|
||||
Inventory openInventory = player.getOpenInventory();
|
||||
// if windowId == 0 then it is player's inventory, meaning that they hadn't been any open inventory packet
|
||||
if (openInventory != null)
|
||||
player.closeInventory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Buffer buffer) {
|
||||
this.windowId = Utils.readVarInt(buffer);
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package fr.themode.minestom.net.packet.client.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||
|
||||
public class ClientConfirmTransactionPacket implements ClientPlayPacket {
|
||||
|
||||
public int windowId;
|
||||
public short actionNumber;
|
||||
public boolean accepted;
|
||||
|
||||
@Override
|
||||
public void process(Player player) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Buffer buffer) {
|
||||
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||
import fr.themode.minestom.utils.Position;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
|
||||
|
||||
public Hand hand;
|
||||
@ -23,9 +25,11 @@ public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
|
||||
if (instance == null)
|
||||
return;
|
||||
|
||||
Random random = new Random();
|
||||
BlockBatch blockBatch = instance.createBlockBatch();
|
||||
for (int x = -64; x < 64; x++)
|
||||
for (int z = -64; z < 64; z++) {
|
||||
if (random.nextInt(100) > 75)
|
||||
blockBatch.setBlock(x, position.getY() + 1, z, new Block(1));
|
||||
}
|
||||
blockBatch.flush();
|
||||
|
@ -0,0 +1,23 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Position;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class BlockChangePacket implements ServerPacket {
|
||||
|
||||
public Position position;
|
||||
public int blockId;
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
Utils.writePosition(buffer, position.getX(), position.getY(), position.getZ());
|
||||
Utils.writeVarInt(buffer, blockId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x0B;
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ public class ChatMessagePacket implements ServerPacket {
|
||||
return 0x0E;
|
||||
}
|
||||
|
||||
public static enum Position {
|
||||
public enum Position {
|
||||
|
||||
CHAT,
|
||||
SYSTEM_MESSAGE,
|
||||
|
@ -0,0 +1,20 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class CloseWindowPacket implements ServerPacket {
|
||||
|
||||
public int windowId;
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
Utils.writeVarInt(buffer, windowId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x13;
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class ConfirmTransactionPacket implements ServerPacket {
|
||||
|
||||
public int windowId;
|
||||
public short actionNumber;
|
||||
public boolean accepted;
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
Utils.writeVarInt(buffer, windowId);
|
||||
buffer.putShort(actionNumber);
|
||||
buffer.putBoolean(accepted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x12;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class MultiBlockChangePacket implements ServerPacket {
|
||||
|
||||
public int chunkX;
|
||||
public int chunkZ;
|
||||
public BlockChange[] blockChanges;
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
buffer.putInt(chunkX);
|
||||
buffer.putInt(chunkZ);
|
||||
Utils.writeVarInt(buffer, blockChanges == null ? 0 : blockChanges.length);
|
||||
|
||||
if (blockChanges != null) {
|
||||
for (int i = 0; i < blockChanges.length; i++) {
|
||||
BlockChange blockChange = blockChanges[i];
|
||||
buffer.putByte(blockChange.positionXZ);
|
||||
buffer.putByte(blockChange.positionY);
|
||||
Utils.writeVarInt(buffer, blockChange.newBlockId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x0F;
|
||||
}
|
||||
|
||||
public static class BlockChange {
|
||||
public byte positionXZ;
|
||||
public byte positionY;
|
||||
public int newBlockId;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class OpenWindowPacket implements ServerPacket {
|
||||
|
||||
public int windowId;
|
||||
public int windowType;
|
||||
public String title;
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
Utils.writeVarInt(buffer, windowId);
|
||||
Utils.writeVarInt(buffer, windowType);
|
||||
Utils.writeString(buffer, "{\"text\": \"" + title + " \"}");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x2E;
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package fr.themode.minestom.net.packet.server.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class SetSlotPacket implements ServerPacket {
|
||||
|
||||
public byte windowId;
|
||||
public short slot;
|
||||
public ItemStack itemStack;
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
buffer.putByte(windowId);
|
||||
buffer.putShort(slot);
|
||||
Utils.writeItemStack(buffer, itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x16;
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ import fr.themode.minestom.utils.Utils;
|
||||
|
||||
public class WindowItemsPacket implements ServerPacket {
|
||||
|
||||
public byte windowId;
|
||||
public int windowId;
|
||||
public short count;
|
||||
public ItemStack[] items;
|
||||
|
||||
@ -15,21 +15,14 @@ public class WindowItemsPacket implements ServerPacket {
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
buffer.putByte(windowId);
|
||||
Utils.writeVarInt(buffer, windowId);
|
||||
buffer.putShort(count);
|
||||
|
||||
if (items == null)
|
||||
return;
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
ItemStack item = items[i];
|
||||
if (item == null) {
|
||||
buffer.putBoolean(false);
|
||||
} else {
|
||||
buffer.putBoolean(true);
|
||||
Utils.writeVarInt(buffer, item.getItemId());
|
||||
buffer.putByte(item.getCount());
|
||||
buffer.putByte((byte) 0); // End nbt TODO
|
||||
}
|
||||
Utils.writeItemStack(buffer, item);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ package fr.themode.minestom.utils;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.instance.Block;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Arrays;
|
||||
@ -132,6 +133,17 @@ public class Utils {
|
||||
return new Position(x, y, z);
|
||||
}
|
||||
|
||||
public static void writeItemStack(Buffer buffer, ItemStack itemStack) {
|
||||
if (itemStack == null) {
|
||||
buffer.putBoolean(false);
|
||||
} else {
|
||||
buffer.putBoolean(true);
|
||||
Utils.writeVarInt(buffer, itemStack.getItemId());
|
||||
buffer.putByte(itemStack.getAmount());
|
||||
buffer.putByte((byte) 0); // End nbt TODO
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeBlocks(Buffer buffer, Block[] blocks, int bitsPerEntry) {
|
||||
buffer.putShort((short) Arrays.stream(blocks).filter(customBlock -> customBlock.getType() != 0).collect(Collectors.toList()).size());
|
||||
buffer.putByte((byte) bitsPerEntry);
|
||||
|
Loading…
Reference in New Issue
Block a user