Better inventory management & typo

This commit is contained in:
Felix Cravic 2020-02-16 19:11:36 +01:00
parent b8319217ab
commit 0cd6eadd7e
20 changed files with 399 additions and 68 deletions

View File

@ -70,7 +70,6 @@ public class Main {
blockManager.registerBlock(new UpdatableBlockDemo()); blockManager.registerBlock(new UpdatableBlockDemo());
server = new Server(); server = new Server();
//server = new Server(136434);
server.onConnect(client -> { server.onConnect(client -> {
System.out.println("CONNECTION"); System.out.println("CONNECTION");

View File

@ -15,7 +15,9 @@ import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.instance.block.CustomBlock; import fr.themode.minestom.instance.block.CustomBlock;
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo; import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
import fr.themode.minestom.inventory.Inventory; import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.inventory.InventoryType;
import fr.themode.minestom.inventory.PlayerInventory; import fr.themode.minestom.inventory.PlayerInventory;
import fr.themode.minestom.inventory.rule.InventoryConditionResult;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.ClientPlayPacket; import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.ServerPacket; import fr.themode.minestom.net.packet.server.ServerPacket;
@ -181,12 +183,21 @@ public class Player extends LivingEntity {
//itemEntity.remove(); //itemEntity.remove();
}*/ }*/
ItemStack item = new ItemStack(1, (byte) 75); ItemStack item = new ItemStack(1, (byte) 4);
item.setDisplayName("LE NOM PUTAIN"); item.setDisplayName("LE NOM PUTAIN");
item.getLore().add("lol le lore"); //item.getLore().add("lol le lore");
item.getLore().add("lol le lore2");
item.getLore().add("lol le lore3");
getInventory().addItemStack(item); getInventory().addItemStack(item);
Inventory inventory = new Inventory(InventoryType.CHEST_1_ROW, "Test inventory");
inventory.setInventoryCondition((slot, inventory1, clickedItem, cursorItem) -> {
InventoryConditionResult result = new InventoryConditionResult(clickedItem, cursorItem);
result.setCancel(false);
return result;
});
inventory.setItemStack(0, item.clone());
openInventory(inventory);
//getInventory().addItemStack(new ItemStack(1, (byte) 100)); //getInventory().addItemStack(new ItemStack(1, (byte) 100));
/*TeamManager teamManager = Main.getTeamManager(); /*TeamManager teamManager = Main.getTeamManager();
@ -482,6 +493,17 @@ public class Player extends LivingEntity {
sendMessage(textObject.toJson()); sendMessage(textObject.toJson());
} }
public void sendActionBarMessage(String message, char colorChar) {
TitlePacket titlePacket = new TitlePacket();
titlePacket.action = TitlePacket.Action.SET_ACTION_BAR;
titlePacket.actionBarText = Chat.legacyText(message, colorChar).toString();
playerConnection.sendPacket(titlePacket);
}
public void sendActionBarMessage(String message) {
sendActionBarMessage(message, Chat.COLOR_CHAR);
}
@Override @Override
public void damage(float value) { public void damage(float value) {
if (getGameMode() == GameMode.CREATIVE) if (getGameMode() == GameMode.CREATIVE)

View File

@ -313,4 +313,4 @@ public class Chunk implements Viewable {
public Set<Player> getViewers() { public Set<Player> getViewers() {
return Collections.unmodifiableSet(viewers); return Collections.unmodifiableSet(viewers);
} }
} }

View File

@ -285,4 +285,4 @@ public abstract class Instance implements BlockModifier, DataContainer {
Set<Entity> entities = chunkEntities.get(index); Set<Entity> entities = chunkEntities.get(index);
return entities != null ? entities : new CopyOnWriteArraySet<>(); return entities != null ? entities : new CopyOnWriteArraySet<>();
} }
} }

View File

@ -259,4 +259,4 @@ public class InstanceContainer extends Instance {
chunk.sendPacketToViewers(blockChangePacket); chunk.sendPacketToViewers(blockChangePacket);
} }
} }

View File

@ -28,7 +28,7 @@ public abstract class CustomBlock {
// TODO add another object parameter which will offer a lot of integrated features (like break animation, id change etc...) // TODO add another object parameter which will offer a lot of integrated features (like break animation, id change etc...)
public void update(Instance instance, BlockPosition blockPosition, Data data) { public void update(Instance instance, BlockPosition blockPosition, Data data) {
throw new UnsupportedOperationException("Update method not overriden"); throw new UnsupportedOperationException("Update method not overridden");
} }
public abstract UpdateOption getUpdateOption(); public abstract UpdateOption getUpdateOption();

View File

@ -2,7 +2,10 @@ package fr.themode.minestom.inventory;
import fr.themode.minestom.Viewable; import fr.themode.minestom.Viewable;
import fr.themode.minestom.entity.Player; import fr.themode.minestom.entity.Player;
import fr.themode.minestom.inventory.rule.InventoryCondition;
import fr.themode.minestom.inventory.rule.InventoryConditionResult;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.item.StackingRule;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket; 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;
@ -27,6 +30,8 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
private Set<Player> viewers = new CopyOnWriteArraySet<>(); private Set<Player> viewers = new CopyOnWriteArraySet<>();
private ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>(); private ConcurrentHashMap<Player, ItemStack> cursorPlayersItem = new ConcurrentHashMap<>();
private InventoryCondition inventoryCondition;
public Inventory(InventoryType inventoryType, String title) { public Inventory(InventoryType inventoryType, String title) {
this.id = generateId(); this.id = generateId();
this.inventoryType = inventoryType; this.inventoryType = inventoryType;
@ -77,6 +82,21 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
return Arrays.copyOf(itemStacks, itemStacks.length); return Arrays.copyOf(itemStacks, itemStacks.length);
} }
@Override
public void setInventoryRule() {
}
@Override
public InventoryCondition getInventoryCondition() {
return inventoryCondition;
}
@Override
public void setInventoryCondition(InventoryCondition inventoryCondition) {
this.inventoryCondition = inventoryCondition;
}
public void update() { public void update() {
WindowItemsPacket windowItemsPacket = getWindowItemsPacket(); WindowItemsPacket windowItemsPacket = getWindowItemsPacket();
getViewers().forEach(p -> p.getPlayerConnection().sendPacket(windowItemsPacket)); getViewers().forEach(p -> p.getPlayerConnection().sendPacket(windowItemsPacket));
@ -138,6 +158,29 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
boolean isInWindow = isClickInWindow(slot); boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset); ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
// Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = inventoryCondition.accept(slot, this, clicked, cursorItem);
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
if (result.isCancel()) {
System.out.println(clicked.getMaterial() + " + " + cursorItem.getMaterial());
if (isInWindow) {
setItemStack(slot, clicked);
setCursorPlayerItem(player, cursorItem);
} else {
playerInventory.setItemStack(slot, offset, clicked);
setCursorPlayerItem(player, cursorItem);
}
// Refresh client window
player.getPlayerConnection().sendPacket(getWindowItemsPacket());
return;
}
}
// End condition
if (cursorItem.isAir() && clicked.isAir()) if (cursorItem.isAir() && clicked.isAir())
return; return;
@ -145,15 +188,21 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
ItemStack resultClicked; ItemStack resultClicked;
if (cursorItem.isSimilar(clicked)) { if (cursorItem.isSimilar(clicked)) {
// They should have the same stacking rule
StackingRule cursorRule = cursorItem.getStackingRule();
StackingRule clickedRule = clicked.getStackingRule();
resultCursor = cursorItem.clone(); resultCursor = cursorItem.clone();
resultClicked = clicked.clone(); resultClicked = clicked.clone();
int totalAmount = cursorItem.getAmount() + clicked.getAmount();
if (totalAmount > 64) { int totalAmount = cursorRule.getAmount(cursorItem) + clickedRule.getAmount(clicked);
resultCursor.setAmount((byte) (totalAmount - 64));
resultClicked.setAmount((byte) 64); if (!clickedRule.canApply(resultClicked, totalAmount)) {
resultCursor = cursorRule.apply(resultCursor, totalAmount - cursorRule.getMaxSize());
resultClicked = clickedRule.apply(resultClicked, clickedRule.getMaxSize());
} else { } else {
resultCursor = ItemStack.AIR_ITEM; resultCursor = cursorRule.apply(resultCursor, 0);
resultClicked.setAmount((byte) totalAmount); resultClicked = clickedRule.apply(resultClicked, totalAmount);
} }
} else { } else {
resultCursor = clicked.clone(); resultCursor = clicked.clone();
@ -176,40 +225,69 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
boolean isInWindow = isClickInWindow(slot); boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset); ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
// Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = inventoryCondition.accept(slot, this, clicked, cursorItem);
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
if (result.isCancel()) {
System.out.println(clicked.getMaterial() + " + " + cursorItem.getMaterial());
if (isInWindow) {
setItemStack(slot, clicked);
setCursorPlayerItem(player, cursorItem);
} else {
playerInventory.setItemStack(slot, offset, clicked);
setCursorPlayerItem(player, cursorItem);
}
// Refresh client window
player.getPlayerConnection().sendPacket(getWindowItemsPacket());
return;
}
}
// End condition
if (cursorItem.isAir() && clicked.isAir()) if (cursorItem.isAir() && clicked.isAir())
return; return;
StackingRule cursorRule = cursorItem.getStackingRule();
StackingRule clickedRule = clicked.getStackingRule();
ItemStack resultCursor; ItemStack resultCursor;
ItemStack resultClicked; ItemStack resultClicked;
if (cursorItem.isSimilar(clicked)) { if (cursorItem.isSimilar(clicked)) {
// They should have the same stacking rule
resultClicked = clicked.clone(); resultClicked = clicked.clone();
int amount = clicked.getAmount() + 1; int amount = clickedRule.getAmount(clicked) + 1;
if (amount > 64) {
if (!cursorRule.canApply(cursorItem, amount)) {
return; return;
} else { } else {
resultCursor = cursorItem.clone(); resultCursor = cursorItem.clone();
resultCursor.setAmount((byte) (resultCursor.getAmount() - 1)); resultCursor = cursorRule.apply(resultCursor, cursorRule.getAmount(resultCursor) - 1);
if (resultCursor.getAmount() < 1) resultClicked = clickedRule.apply(resultClicked, amount);
resultCursor = ItemStack.AIR_ITEM;
resultClicked.setAmount((byte) amount);
} }
} else { } else {
if (cursorItem.isAir()) { if (cursorItem.isAir()) {
int amount = (int) Math.ceil((double) clicked.getAmount() / 2d); int amount = (int) Math.ceil((double) clicked.getAmount() / 2d);
resultCursor = clicked.clone(); resultCursor = clicked.clone();
resultCursor.setAmount((byte) amount); resultCursor = cursorRule.apply(resultCursor, amount);
resultClicked = clicked.clone(); resultClicked = clicked.clone();
resultClicked.setAmount((byte) (clicked.getAmount() / 2)); resultClicked = clickedRule.apply(resultClicked, clicked.getAmount() / 2);
} else { } else {
if (clicked.isAir()) { if (clicked.isAir()) {
int amount = cursorItem.getAmount(); int amount = cursorItem.getAmount();
resultCursor = cursorItem.clone(); resultCursor = cursorItem.clone();
resultCursor.setAmount((byte) (amount - 1)); resultCursor = cursorRule.apply(resultCursor, amount - 1);
if (resultCursor.getAmount() < 1)
resultCursor = ItemStack.AIR_ITEM;
resultClicked = cursorItem.clone(); resultClicked = cursorItem.clone();
resultClicked.setAmount((byte) 1); resultClicked = clickedRule.apply(resultClicked, 1);
} else { } else {
resultCursor = clicked.clone(); resultCursor = clicked.clone();
resultClicked = cursorItem.clone(); resultClicked = cursorItem.clone();
@ -231,6 +309,30 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
PlayerInventory playerInventory = player.getInventory(); PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot); boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset); ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack cursorItem = getCursorItem(player); // Isn't used in the algorithm
// Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = inventoryCondition.accept(slot, this, clicked, cursorItem);
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
if (result.isCancel()) {
System.out.println(clicked.getMaterial() + " + " + cursorItem.getMaterial());
if (isInWindow) {
setItemStack(slot, clicked);
setCursorPlayerItem(player, cursorItem);
} else {
playerInventory.setItemStack(slot, offset, clicked);
setCursorPlayerItem(player, cursorItem);
}
// Refresh client window
player.getPlayerConnection().sendPacket(getWindowItemsPacket());
return;
}
}
// End condition
if (clicked.isAir()) if (clicked.isAir())
return; return;
@ -238,22 +340,25 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
ItemStack resultClicked = clicked.clone(); ItemStack resultClicked = clicked.clone();
boolean filled = false; boolean filled = false;
StackingRule clickedRule = clicked.getStackingRule();
int maxSize = clickedRule.getMaxSize();
if (!isInWindow) { if (!isInWindow) {
for (int i = 0; i < itemStacks.length; i++) { for (int i = 0; i < itemStacks.length; i++) {
ItemStack item = itemStacks[i]; ItemStack item = itemStacks[i];
if (item.isSimilar(clicked)) { if (item.isSimilar(clicked)) {
int amount = item.getAmount(); int amount = item.getAmount();
if (amount == 64) if (amount == maxSize)
continue; continue;
int totalAmount = resultClicked.getAmount() + amount; int totalAmount = resultClicked.getAmount() + amount;
if (totalAmount > 64) { if (!clickedRule.canApply(clicked, totalAmount)) {
item.setAmount((byte) 64); item = clickedRule.apply(item, maxSize);
setItemStack(i, item); setItemStack(i, item);
resultClicked.setAmount((byte) (totalAmount - 64)); resultClicked = clickedRule.apply(resultClicked, totalAmount - maxSize);
filled = false; filled = false;
continue; continue;
} else { } else {
resultClicked.setAmount((byte) totalAmount); resultClicked = clickedRule.apply(resultClicked, totalAmount);
setItemStack(i, resultClicked); setItemStack(i, resultClicked);
playerInventory.setItemStack(slot, offset, ItemStack.AIR_ITEM); playerInventory.setItemStack(slot, offset, ItemStack.AIR_ITEM);
filled = true; filled = true;
@ -275,17 +380,17 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
ItemStack item = playerInventory.getItemStack(i, offset); ItemStack item = playerInventory.getItemStack(i, offset);
if (item.isSimilar(clicked)) { if (item.isSimilar(clicked)) {
int amount = item.getAmount(); int amount = item.getAmount();
if (amount == 64) if (amount == maxSize)
continue; continue;
int totalAmount = resultClicked.getAmount() + amount; int totalAmount = resultClicked.getAmount() + amount;
if (totalAmount > 64) { if (!clickedRule.canApply(clicked, totalAmount)) {
item.setAmount((byte) 64); item = clickedRule.apply(item, maxSize);
playerInventory.setItemStack(i, offset, item); playerInventory.setItemStack(i, offset, item);
resultClicked.setAmount((byte) (totalAmount - 64)); resultClicked = clickedRule.apply(resultClicked, totalAmount - maxSize);
filled = false; filled = false;
continue; continue;
} else { } else {
resultClicked.setAmount((byte) totalAmount); resultClicked = clickedRule.apply(resultClicked, totalAmount);
playerInventory.setItemStack(i, offset, resultClicked); playerInventory.setItemStack(i, offset, resultClicked);
setItemStack(slot, ItemStack.AIR_ITEM); setItemStack(slot, ItemStack.AIR_ITEM);
filled = true; filled = true;
@ -308,13 +413,37 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override @Override
public void changeHeld(Player player, int slot, int key) { public void changeHeld(Player player, int slot, int key) {
PlayerInventory playerInventory = player.getInventory(); PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack cursorItem = getCursorItem(player);
if (!getCursorItem(player).isAir()) // Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = inventoryCondition.accept(slot, this, clicked, cursorItem);
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
if (result.isCancel()) {
System.out.println(clicked.getMaterial() + " + " + cursorItem.getMaterial());
if (isInWindow) {
setItemStack(slot, clicked);
setCursorPlayerItem(player, cursorItem);
} else {
playerInventory.setItemStack(slot, offset, clicked);
setCursorPlayerItem(player, cursorItem);
}
// Refresh client window
player.getPlayerConnection().sendPacket(getWindowItemsPacket());
return;
}
}
// End condition
if (!cursorItem.isAir())
return; return;
boolean isInWindow = isClickInWindow(slot);
ItemStack heldItem = playerInventory.getItemStack(key); ItemStack heldItem = playerInventory.getItemStack(key);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset);
ItemStack resultClicked; ItemStack resultClicked;
ItemStack resultHeld; ItemStack resultHeld;
@ -361,27 +490,56 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
@Override @Override
public void doubleClick(Player player, int slot) { public void doubleClick(Player player, int slot) {
PlayerInventory playerInventory = player.getInventory(); PlayerInventory playerInventory = player.getInventory();
boolean isInWindow = isClickInWindow(slot);
ItemStack clicked = isInWindow ? getItemStack(slot) : playerInventory.getItemStack(slot, offset); // Isn't used in the algorithm
ItemStack cursorItem = getCursorItem(player).clone(); ItemStack cursorItem = getCursorItem(player).clone();
// Start condition
InventoryCondition inventoryCondition = getInventoryCondition();
if (inventoryCondition != null) {
InventoryConditionResult result = inventoryCondition.accept(slot, this, clicked, cursorItem);
cursorItem = result.getCursorItem();
clicked = result.getClickedItem();
if (result.isCancel()) {
System.out.println(clicked.getMaterial() + " + " + cursorItem.getMaterial());
if (isInWindow) {
setItemStack(slot, clicked);
setCursorPlayerItem(player, cursorItem);
} else {
playerInventory.setItemStack(slot, offset, clicked);
setCursorPlayerItem(player, cursorItem);
}
// Refresh client window
player.getPlayerConnection().sendPacket(getWindowItemsPacket());
return;
}
}
// End condition
if (cursorItem.isAir()) if (cursorItem.isAir())
return; return;
int amount = cursorItem.getAmount(); int amount = cursorItem.getAmount();
if (amount == 64) StackingRule cursorRule = cursorItem.getStackingRule();
int maxSize = cursorRule.getMaxSize();
if (amount == maxSize)
return; return;
// Start by looping through the opened inventory // Start by looping through the opened inventory
for (int i = 0; i < itemStacks.length; i++) { for (int i = 0; i < itemStacks.length; i++) {
if (i == slot) if (i == slot)
continue; continue;
if (amount == 64) if (amount == maxSize)
break; break;
ItemStack item = itemStacks[i]; ItemStack item = itemStacks[i];
if (cursorItem.isSimilar(item)) { if (cursorItem.isSimilar(item)) {
int totalAmount = amount + item.getAmount(); int totalAmount = amount + item.getAmount();
if (totalAmount > 64) { if (!cursorRule.canApply(cursorItem, totalAmount)) {
cursorItem.setAmount((byte) 64); cursorItem = cursorRule.apply(cursorItem, maxSize);
item.setAmount((byte) (totalAmount - 64)); item = cursorRule.apply(item, totalAmount - maxSize);
setItemStack(i, item); setItemStack(i, item);
} else { } else {
cursorItem.setAmount((byte) totalAmount); cursorItem.setAmount((byte) totalAmount);
@ -395,14 +553,14 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
for (int i = 9; i < PlayerInventory.INVENTORY_SIZE - 9; i++) { // Inventory for (int i = 9; i < PlayerInventory.INVENTORY_SIZE - 9; i++) { // Inventory
if (playerInventory.convertToPacketSlot(i) == slot) if (playerInventory.convertToPacketSlot(i) == slot)
continue; continue;
if (amount == 64) if (amount == maxSize)
break; break;
ItemStack item = playerInventory.getItemStack(i); ItemStack item = playerInventory.getItemStack(i);
if (cursorItem.isSimilar(item)) { if (cursorItem.isSimilar(item)) {
int totalAmount = amount + item.getAmount(); int totalAmount = amount + item.getAmount();
if (totalAmount > 64) { if (!cursorRule.canApply(cursorItem, totalAmount)) {
cursorItem.setAmount((byte) 64); cursorItem = cursorRule.apply(cursorItem, maxSize);
item.setAmount((byte) (totalAmount - 64)); item = cursorRule.apply(item, totalAmount - maxSize);
playerInventory.setItemStack(i, offset, item); playerInventory.setItemStack(i, offset, item);
} else { } else {
cursorItem.setAmount((byte) totalAmount); cursorItem.setAmount((byte) totalAmount);
@ -415,14 +573,14 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
for (int i = 0; i < 9; i++) { // Hotbar for (int i = 0; i < 9; i++) { // Hotbar
if (playerInventory.convertToPacketSlot(i) == slot) if (playerInventory.convertToPacketSlot(i) == slot)
continue; continue;
if (amount == 64) if (amount == maxSize)
break; break;
ItemStack item = playerInventory.getItemStack(i); ItemStack item = playerInventory.getItemStack(i);
if (cursorItem.isSimilar(item)) { if (cursorItem.isSimilar(item)) {
int totalAmount = amount + item.getAmount(); int totalAmount = amount + item.getAmount();
if (totalAmount > 64) { if (!cursorRule.canApply(cursorItem, totalAmount)) {
cursorItem.setAmount((byte) 64); cursorItem = cursorRule.apply(cursorItem, maxSize);
item.setAmount((byte) (totalAmount - 64)); item = cursorRule.apply(item, totalAmount - maxSize);
playerInventory.setItemStack(i, offset, item); playerInventory.setItemStack(i, offset, item);
} else { } else {
cursorItem.setAmount((byte) totalAmount); cursorItem.setAmount((byte) totalAmount);

View File

@ -1,5 +1,6 @@
package fr.themode.minestom.inventory; package fr.themode.minestom.inventory;
import fr.themode.minestom.inventory.rule.InventoryCondition;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
public interface InventoryModifier { public interface InventoryModifier {
@ -11,4 +12,10 @@ public interface InventoryModifier {
ItemStack getItemStack(int slot); ItemStack getItemStack(int slot);
ItemStack[] getItemStacks(); ItemStack[] getItemStacks();
void setInventoryRule();
InventoryCondition getInventoryCondition();
void setInventoryCondition(InventoryCondition inventoryCondition);
} }

View File

@ -0,0 +1,4 @@
package fr.themode.minestom.inventory;
public class InventoryRule {
}

View File

@ -1,6 +1,7 @@
package fr.themode.minestom.inventory; package fr.themode.minestom.inventory;
import fr.themode.minestom.entity.Player; import fr.themode.minestom.entity.Player;
import fr.themode.minestom.inventory.rule.InventoryCondition;
import fr.themode.minestom.item.ItemStack; import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.server.play.EntityEquipmentPacket; import fr.themode.minestom.net.packet.server.play.EntityEquipmentPacket;
import fr.themode.minestom.net.packet.server.play.SetSlotPacket; import fr.themode.minestom.net.packet.server.play.SetSlotPacket;
@ -32,6 +33,8 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
private ItemStack[] items = new ItemStack[INVENTORY_SIZE]; private ItemStack[] items = new ItemStack[INVENTORY_SIZE];
private ItemStack cursorItem = ItemStack.AIR_ITEM; private ItemStack cursorItem = ItemStack.AIR_ITEM;
private InventoryCondition inventoryCondition;
public PlayerInventory(Player player) { public PlayerInventory(Player player) {
this.player = player; this.player = player;
@ -48,6 +51,21 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler
return Arrays.copyOf(items, items.length); return Arrays.copyOf(items, items.length);
} }
@Override
public void setInventoryRule() {
}
@Override
public InventoryCondition getInventoryCondition() {
return inventoryCondition;
}
@Override
public void setInventoryCondition(InventoryCondition inventoryCondition) {
this.inventoryCondition = inventoryCondition;
}
@Override @Override
public void setItemStack(int slot, ItemStack itemStack) { public void setItemStack(int slot, ItemStack itemStack) {
safeItemInsert(slot, itemStack); safeItemInsert(slot, itemStack);

View File

@ -0,0 +1,10 @@
package fr.themode.minestom.inventory.rule;
import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.item.ItemStack;
public interface InventoryCondition {
InventoryConditionResult accept(int slot, Inventory inventory, ItemStack clickedItem, ItemStack cursorItem);
}

View File

@ -0,0 +1,38 @@
package fr.themode.minestom.inventory.rule;
import fr.themode.minestom.item.ItemStack;
public class InventoryConditionResult {
private ItemStack clickedItem, cursorItem;
private boolean cancel;
public InventoryConditionResult(ItemStack clickedItem, ItemStack cursorItem) {
this.clickedItem = clickedItem;
this.cursorItem = cursorItem;
}
public ItemStack getClickedItem() {
return clickedItem;
}
public void setClickedItem(ItemStack clickedItem) {
this.clickedItem = clickedItem;
}
public ItemStack getCursorItem() {
return cursorItem;
}
public void setCursorItem(ItemStack cursorItem) {
this.cursorItem = cursorItem;
}
public boolean isCancel() {
return cancel;
}
public void setCancel(boolean cancel) {
this.cancel = cancel;
}
}

View File

@ -2,6 +2,7 @@ package fr.themode.minestom.item;
import fr.themode.minestom.data.Data; import fr.themode.minestom.data.Data;
import fr.themode.minestom.data.DataContainer; import fr.themode.minestom.data.DataContainer;
import fr.themode.minestom.item.rule.VanillaStackingRule;
import java.util.ArrayList; import java.util.ArrayList;
@ -17,6 +18,7 @@ public class ItemStack implements DataContainer {
private boolean unbreakable; private boolean unbreakable;
private ArrayList<String> lore; private ArrayList<String> lore;
private StackingRule stackingRule = new VanillaStackingRule((byte) 64);
private Data data; private Data data;
public ItemStack(Material material, byte amount, short damage) { public ItemStack(Material material, byte amount, short damage) {
@ -45,6 +47,7 @@ public class ItemStack implements DataContainer {
itemStack.getDisplayName() == displayName && itemStack.getDisplayName() == displayName &&
itemStack.isUnbreakable() == unbreakable && itemStack.isUnbreakable() == unbreakable &&
itemStack.getDamage() == damage && itemStack.getDamage() == damage &&
itemStack.getStackingRule() == stackingRule &&
itemStack.getData() == data; itemStack.getData() == data;
} }
@ -108,12 +111,25 @@ public class ItemStack implements DataContainer {
ItemStack itemStack = new ItemStack(material, amount, damage); ItemStack itemStack = new ItemStack(material, amount, damage);
itemStack.setDisplayName(displayName); itemStack.setDisplayName(displayName);
itemStack.setUnbreakable(unbreakable); itemStack.setUnbreakable(unbreakable);
itemStack.setLore(getLore());
itemStack.setStackingRule(getStackingRule());
Data data = getData(); Data data = getData();
if (data != null) if (data != null)
itemStack.setData(data.clone()); itemStack.setData(data.clone());
return itemStack; return itemStack;
} }
public StackingRule getStackingRule() {
return stackingRule;
}
public void setStackingRule(StackingRule stackingRule) {
if (stackingRule == null)
throw new NullPointerException("StackingRule cannot be null!");
this.stackingRule = stackingRule;
}
@Override @Override
public Data getData() { public Data getData() {
return data; return data;

View File

@ -0,0 +1,20 @@
package fr.themode.minestom.item;
public abstract class StackingRule {
private int maxSize;
public StackingRule(int maxSize) {
this.maxSize = maxSize;
}
public abstract boolean canApply(ItemStack item, int newAmount);
public abstract ItemStack apply(ItemStack item, int newAmount);
public abstract int getAmount(ItemStack itemStack);
public int getMaxSize() {
return maxSize;
}
}

View File

@ -0,0 +1,30 @@
package fr.themode.minestom.item.rule;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.item.StackingRule;
public class VanillaStackingRule extends StackingRule {
public VanillaStackingRule(int maxSize) {
super(maxSize);
}
@Override
public boolean canApply(ItemStack item, int newAmount) {
return newAmount >= 1 && newAmount <= getMaxSize();
}
@Override
public ItemStack apply(ItemStack item, int newAmount) {
if (newAmount <= 0)
return ItemStack.AIR_ITEM;
item.setAmount((byte) newAmount);
return item;
}
@Override
public int getAmount(ItemStack itemStack) {
return itemStack.getAmount();
}
}

View File

@ -1,7 +1,5 @@
package fr.themode.minestom.net; package fr.themode.minestom.net;
public enum ConnectionState { public enum ConnectionState {
UNKNOWN, STATUS, LOGIN, PLAY; UNKNOWN, STATUS, LOGIN, PLAY;
} }

View File

@ -41,9 +41,9 @@ public class PacketProcessor {
public void process(Client client, int id, int length, int offset) { public void process(Client client, int id, int length, int offset) {
PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(client, c -> new PlayerConnection(client)); PlayerConnection playerConnection = connectionPlayerConnectionMap.computeIfAbsent(client, c -> new PlayerConnection(client));
ConnectionState connectionState = playerConnection.getConnectionState(); ConnectionState connectionState = playerConnection.getConnectionState();
if (!printBlackList.contains(id)) { /*if (!printBlackList.contains(id)) {
//System.out.println("RECEIVED ID: 0x" + Integer.toHexString(id) + " State: " + connectionState); System.out.println("RECEIVED ID: 0x" + Integer.toHexString(id) + " State: " + connectionState);
} }*/
PacketReader packetReader = new PacketReader(client, length, offset); PacketReader packetReader = new PacketReader(client, length, offset);

View File

@ -132,4 +132,4 @@ public class ChunkDataPacket implements ServerPacket {
public int getId() { public int getId() {
return ServerPacketIdentifier.CHUNK_DATA; return ServerPacketIdentifier.CHUNK_DATA;
} }
} }

View File

@ -7,14 +7,16 @@ import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.PacketReader; import fr.themode.minestom.net.packet.PacketReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.function.Consumer;
public class NbtReaderUtils { public class NbtReaderUtils {
public static void readItemStackNBT(PacketReader reader, ItemStack item) { public static void readItemStackNBT(PacketReader reader, Consumer<ItemStack> consumer, ItemStack item) {
reader.readByte(typeId -> { reader.readByte(typeId -> {
switch (typeId) { switch (typeId) {
case 0x00: // TAG_End case 0x00: // TAG_End
// End of item NBT // End of item NBT
consumer.accept(item);
break; break;
case 0x01: // TAG_Byte case 0x01: // TAG_Byte
@ -26,7 +28,7 @@ public class NbtReaderUtils {
if (name.equals("Damage")) { if (name.equals("Damage")) {
reader.readShort(damage -> { reader.readShort(damage -> {
item.setDamage(damage); item.setDamage(damage);
readItemStackNBT(reader, item); readItemStackNBT(reader, consumer, item);
}); });
} }
@ -39,7 +41,7 @@ public class NbtReaderUtils {
if (name.equals("Unbreakable")) { if (name.equals("Unbreakable")) {
reader.readInteger(value -> { reader.readInteger(value -> {
item.setUnbreakable(value == 1); item.setUnbreakable(value == 1);
readItemStackNBT(reader, item); readItemStackNBT(reader, consumer, item);
}); });
} }
@ -69,7 +71,7 @@ public class NbtReaderUtils {
// Display Compound // Display Compound
if (compoundName.equals("display")) { if (compoundName.equals("display")) {
readItemStackDisplayNBT(reader, item); readItemStackDisplayNBT(reader, consumer, item);
} }
}); });
@ -79,13 +81,13 @@ public class NbtReaderUtils {
}); });
} }
public static void readItemStackDisplayNBT(PacketReader reader, ItemStack item) { public static void readItemStackDisplayNBT(PacketReader reader, Consumer<ItemStack> consumer, ItemStack item) {
reader.readByte(typeId -> { reader.readByte(typeId -> {
switch (typeId) { switch (typeId) {
case 0x00: // TAG_End case 0x00: // TAG_End
// End of the display compound // End of the display compound
readItemStackNBT(reader, item); readItemStackNBT(reader, consumer, item);
break; break;
case 0x08: // TAG_String case 0x08: // TAG_String
@ -96,7 +98,7 @@ public class NbtReaderUtils {
TextObject textObject = TextObject.fromJson(new JsonParser().parse(jsonDisplayName).getAsJsonObject()); TextObject textObject = TextObject.fromJson(new JsonParser().parse(jsonDisplayName).getAsJsonObject());
String displayName = LegacyText.toLegacy(textObject); String displayName = LegacyText.toLegacy(textObject);
item.setDisplayName(displayName); item.setDisplayName(displayName);
readItemStackDisplayNBT(reader, item); readItemStackDisplayNBT(reader, consumer, item);
}); });
} }
@ -117,9 +119,12 @@ public class NbtReaderUtils {
TextObject textObject = TextObject.fromJson(new JsonParser().parse(string).getAsJsonObject()); TextObject textObject = TextObject.fromJson(new JsonParser().parse(string).getAsJsonObject());
String line = LegacyText.toLegacy(textObject); String line = LegacyText.toLegacy(textObject);
lore.add(line); lore.add(line);
if (lore.size() == size) {
item.setLore(lore);
}
}); });
if (i == size - 1) { // Last iteration if (i == size - 1) { // Last iteration
readItemStackDisplayNBT(reader, item); readItemStackDisplayNBT(reader, consumer, item);
} }
} }

View File

@ -177,6 +177,12 @@ public class Utils {
} }
reader.readVarInt(id -> { reader.readVarInt(id -> {
if (id == -1) {
// Drop mode
consumer.accept(ItemStack.AIR_ITEM);
}
reader.readByte(count -> { reader.readByte(count -> {
ItemStack item = new ItemStack(id, count); ItemStack item = new ItemStack(id, count);
reader.readByte(nbt -> { // Should be compound start (0x0A) or 0 if there isn't NBT data reader.readByte(nbt -> { // Should be compound start (0x0A) or 0 if there isn't NBT data
@ -185,7 +191,7 @@ public class Utils {
return; return;
} else if (nbt == 0x0A) { } else if (nbt == 0x0A) {
reader.readShort(compoundName -> { // Ignored, should be empty (main compound name) reader.readShort(compoundName -> { // Ignored, should be empty (main compound name)
NbtReaderUtils.readItemStackNBT(reader, item); NbtReaderUtils.readItemStackNBT(reader, consumer, item);
}); });
} }