cn.nukkit.inventory.PlayerInventory Maven / Gradle / Ivy
package cn.nukkit.inventory;
import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.block.Block;
import cn.nukkit.block.BlockID;
import cn.nukkit.entity.EntityHuman;
import cn.nukkit.entity.EntityHumanType;
import cn.nukkit.event.entity.EntityArmorChangeEvent;
import cn.nukkit.event.entity.EntityInventoryChangeEvent;
import cn.nukkit.event.player.PlayerItemHeldEvent;
import cn.nukkit.item.Item;
import cn.nukkit.item.ItemArmor;
import cn.nukkit.item.ItemBlock;
import cn.nukkit.level.vibration.VibrationEvent;
import cn.nukkit.level.vibration.VibrationType;
import cn.nukkit.network.protocol.*;
import cn.nukkit.network.protocol.types.ContainerIds;
import java.util.Collection;
/**
* 0-8 物品栏
* 9-35 背包
* 36-39 盔甲栏
* 想获取副手库存请用{@link PlayerOffhandInventory}
*
* @author MagicDroidX (Nukkit Project)
*/
public class PlayerInventory extends BaseInventory {
protected int itemInHandIndex = 0;
private int[] hotbar;
public PlayerInventory(EntityHumanType player) {
super(player, InventoryType.PLAYER);
this.hotbar = new int[this.getHotbarSize()];
for (int i = 0; i < this.hotbar.length; i++) {
this.hotbar[i] = i;
}
}
@Override
public int getSize() {
return super.getSize() - 4;
}
@Override
public void setSize(int size) {
super.setSize(size + 4);
this.sendContents(this.getViewers());
}
/**
* Called when a client equips a hotbar inventorySlot. This method should not be used by plugins.
* This method will call PlayerItemHeldEvent.
*
* @param slot hotbar slot Number of the hotbar slot to equip.
* @return boolean if the equipment change was successful, false if not.
*/
public boolean equipItem(int slot) {
if (!isHotbarSlot(slot)) {
this.sendContents((Player) this.getHolder());
return false;
}
if (this.getHolder() instanceof Player) {
Player player = (Player) this.getHolder();
PlayerItemHeldEvent ev = new PlayerItemHeldEvent(player, this.getItem(slot), slot);
this.getHolder().getLevel().getServer().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
this.sendContents(this.getViewers());
return false;
}
if (player.fishing != null) {
if (!(this.getItem(slot).equals(player.fishing.rod))) {
player.stopFishing(false);
}
}
}
this.setHeldItemIndex(slot, false);
return true;
}
private boolean isHotbarSlot(int slot) {
return slot >= 0 && slot <= this.getHotbarSize();
}
@Deprecated
public int getHotbarSlotIndex(int index) {
return index;
}
@Deprecated
public void setHotbarSlotIndex(int index, int slot) {
}
public int getHeldItemIndex() {
return this.itemInHandIndex;
}
public void setHeldItemIndex(int index) {
setHeldItemIndex(index, true);
}
public void setHeldItemIndex(int index, boolean send) {
if (index >= 0 && index < this.getHotbarSize()) {
this.itemInHandIndex = index;
if (this.getHolder() instanceof Player && send) {
this.sendHeldItem((Player) this.getHolder());
}
this.sendHeldItem(this.getHolder().getViewers().values());
}
}
public Item getItemInHand() {
Item item = this.getItem(this.getHeldItemIndex());
if (item != null) {
return item;
} else {
return new ItemBlock(Block.get(BlockID.AIR), 0, 0);
}
}
public boolean setItemInHand(Item item) {
return this.setItem(this.getHeldItemIndex(), item);
}
@Deprecated
public int getHeldItemSlot() {
return this.itemInHandIndex;
}
public void setHeldItemSlot(int slot) {
if (!isHotbarSlot(slot)) {
return;
}
this.itemInHandIndex = slot;
if (this.getHolder() instanceof Player) {
this.sendHeldItem((Player) this.getHolder());
}
this.sendHeldItem(this.getViewers());
}
public void sendHeldItem(Player... players) {
Item item = this.getItemInHand();
MobEquipmentPacket pk = new MobEquipmentPacket();
pk.item = item;
pk.inventorySlot = pk.hotbarSlot = this.getHeldItemIndex();
for (Player player : players) {
pk.eid = this.getHolder().getId();
if (player.equals(this.getHolder())) {
pk.eid = player.getId();
this.sendSlot(this.getHeldItemIndex(), player);
}
player.dataPacket(pk);
}
}
public void sendHeldItem(Collection players) {
this.sendHeldItem(players.toArray(Player.EMPTY_ARRAY));
}
@Override
public void onSlotChange(int index, Item before, boolean send) {
EntityHuman holder = this.getHolder();
if (holder instanceof Player && !((Player) holder).spawned) {
return;
}
if (index >= this.getSize()) {
this.sendArmorSlot(index, this.getViewers());
this.sendArmorSlot(index, this.getHolder().getViewers().values());
if (this.getItem(index) instanceof ItemArmor) {
this.getHolder().level.getVibrationManager().callVibrationEvent(new VibrationEvent(getHolder(), this.getHolder().clone(), VibrationType.EQUIP));
}
} else {
super.onSlotChange(index, before, send);
}
}
public int getHotbarSize() {
return 9;
}
public Item getArmorItem(int index) {
return this.getItem(this.getSize() + index);
}
public boolean setArmorItem(int index, Item item) {
return this.setArmorItem(index, item, false);
}
public boolean setArmorItem(int index, Item item, boolean ignoreArmorEvents) {
return this.setItem(this.getSize() + index, item, ignoreArmorEvents);
}
public Item getHelmet() {
return this.getItem(this.getSize());
}
public Item getChestplate() {
return this.getItem(this.getSize() + 1);
}
public Item getLeggings() {
return this.getItem(this.getSize() + 2);
}
public Item getBoots() {
return this.getItem(this.getSize() + 3);
}
public boolean setHelmet(Item helmet) {
return this.setItem(this.getSize(), helmet);
}
public boolean setChestplate(Item chestplate) {
return this.setItem(this.getSize() + 1, chestplate);
}
public boolean setLeggings(Item leggings) {
return this.setItem(this.getSize() + 2, leggings);
}
public boolean setBoots(Item boots) {
return this.setItem(this.getSize() + 3, boots);
}
@Override
public boolean setItem(int index, Item item) {
return setItem(index, item, true, false);
}
@Override
public boolean setItem(int index, Item item, boolean send) {
return setItem(index, item, send, false);
}
private boolean setItem(int index, Item item, boolean send, boolean ignoreArmorEvents) {
if (index < 0 || index >= this.size) {
return false;
} else if (item.getId() == 0 || item.getCount() <= 0) {
return this.clear(index);
}
//Armor change
if (!ignoreArmorEvents && index >= this.getSize()) {
EntityArmorChangeEvent ev = new EntityArmorChangeEvent(this.getHolder(), this.getItem(index), item, index);
Server.getInstance().getPluginManager().callEvent(ev);
if (ev.isCancelled() && this.getHolder() != null) {
this.sendArmorSlot(index, this.getViewers());
return false;
}
item = ev.getNewItem();
} else {
EntityInventoryChangeEvent ev = new EntityInventoryChangeEvent(this.getHolder(), this.getItem(index), item, index);
Server.getInstance().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
this.sendSlot(index, this.getViewers());
return false;
}
item = ev.getNewItem();
}
Item old = this.getItem(index);
this.slots.put(index, item.clone());
this.onSlotChange(index, old, send);
return true;
}
@Override
public boolean clear(int index, boolean send) {
if (this.slots.containsKey(index)) {
Item item = new ItemBlock(Block.get(BlockID.AIR), null, 0);
Item old = this.slots.get(index);
if (index >= this.getSize() && index < this.size) {
EntityArmorChangeEvent ev = new EntityArmorChangeEvent(this.getHolder(), old, item, index);
Server.getInstance().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
if (index >= this.size) {
this.sendArmorSlot(index, this.getViewers());
} else {
this.sendSlot(index, this.getViewers());
}
return false;
}
item = ev.getNewItem();
} else {
EntityInventoryChangeEvent ev = new EntityInventoryChangeEvent(this.getHolder(), old, item, index);
Server.getInstance().getPluginManager().callEvent(ev);
if (ev.isCancelled()) {
if (index >= this.size) {
this.sendArmorSlot(index, this.getViewers());
} else {
this.sendSlot(index, this.getViewers());
}
return false;
}
item = ev.getNewItem();
}
if (item.getId() != Item.AIR) {
this.slots.put(index, item.clone());
} else {
this.slots.remove(index);
}
this.onSlotChange(index, old, send);
}
return true;
}
public Item[] getArmorContents() {
Item[] armor = new Item[4];
for (int i = 0; i < 4; i++) {
armor[i] = this.getItem(this.getSize() + i);
}
return armor;
}
@Override
public void clearAll() {
int limit = this.getSize() + 4;
for (int index = 0; index < limit; ++index) {
this.clear(index);
}
getHolder().getOffhandInventory().clearAll();
}
public void sendArmorContents(Player player) {
this.sendArmorContents(new Player[]{player});
}
public void sendArmorContents(Player[] players) {
Item[] armor = this.getArmorContents();
MobArmorEquipmentPacket pk = new MobArmorEquipmentPacket();
pk.eid = this.getHolder().getId();
pk.slots = armor;
pk.tryEncode();
for (Player player : players) {
if (player.equals(this.getHolder())) {
InventoryContentPacket pk2 = new InventoryContentPacket();
pk2.inventoryId = InventoryContentPacket.SPECIAL_ARMOR;
pk2.slots = armor;
player.dataPacket(pk2);
} else {
player.dataPacket(pk);
}
}
}
public void setArmorContents(Item[] items) {
if (items.length < 4) {
Item[] newItems = new Item[4];
System.arraycopy(items, 0, newItems, 0, items.length);
items = newItems;
}
for (int i = 0; i < 4; ++i) {
if (items[i] == null) {
items[i] = new ItemBlock(Block.get(BlockID.AIR), null, 0);
}
if (items[i].getId() == Item.AIR) {
this.clear(this.getSize() + i);
} else {
this.setItem(this.getSize() + i, items[i]);
}
}
}
public void sendArmorContents(Collection players) {
this.sendArmorContents(players.toArray(Player.EMPTY_ARRAY));
}
public void sendArmorSlot(int index, Player player) {
this.sendArmorSlot(index, new Player[]{player});
}
public void sendArmorSlot(int index, Player[] players) {
Item[] armor = this.getArmorContents();
MobArmorEquipmentPacket pk = new MobArmorEquipmentPacket();
pk.eid = this.getHolder().getId();
pk.slots = armor;
pk.tryEncode();
for (Player player : players) {
if (player.equals(this.getHolder())) {
InventorySlotPacket pk2 = new InventorySlotPacket();
pk2.inventoryId = InventoryContentPacket.SPECIAL_ARMOR;
pk2.slot = index - this.getSize();
pk2.item = this.getItem(index);
player.dataPacket(pk2);
} else {
player.dataPacket(pk);
}
}
}
public void sendArmorSlot(int index, Collection players) {
this.sendArmorSlot(index, players.toArray(Player.EMPTY_ARRAY));
}
@Override
public void sendContents(Player player) {
this.sendContents(new Player[]{player});
}
@Override
public void sendContents(Collection players) {
this.sendContents(players.toArray(Player.EMPTY_ARRAY));
}
@Override
public void sendContents(Player[] players) {
InventoryContentPacket pk = new InventoryContentPacket();
pk.slots = new Item[this.getSize()];
for (int i = 0; i < this.getSize(); ++i) {
pk.slots[i] = this.getItem(i);
}
/*//Because PE is stupid and shows 9 less slots than you send it, give it 9 dummy slots so it shows all the REAL slots.
for(int i = this.getSize(); i < this.getSize() + this.getHotbarSize(); ++i){
pk.slots[i] = new ItemBlock(Block.get(BlockID.AIR));
}
pk.slots[i] = new ItemBlock(Block.get(BlockID.AIR));
}*/
for (Player player : players) {
int id = player.getWindowId(this);
if (id == -1 || !player.spawned) {
if (this.getHolder() != player) this.close(player);
continue;
}
pk.inventoryId = id;
player.dataPacket(pk.clone());
}
}
@Override
public void sendSlot(int index, Player player) {
this.sendSlot(index, new Player[]{player});
}
@Override
public void sendSlot(int index, Collection players) {
this.sendSlot(index, players.toArray(Player.EMPTY_ARRAY));
}
@Override
public void sendSlot(int index, Player... players) {
InventorySlotPacket pk = new InventorySlotPacket();
pk.slot = index;
pk.item = this.getItem(index).clone();
for (Player player : players) {
if (player.equals(this.getHolder())) {
pk.inventoryId = ContainerIds.INVENTORY;
player.dataPacket(pk);
} else {
int id = player.getWindowId(this);
if (id == -1) {
this.close(player);
continue;
}
pk.inventoryId = id;
player.dataPacket(pk.clone());
}
}
}
public void sendCreativeContents() {
if (!(this.getHolder() instanceof Player)) {
return;
}
Player p = (Player) this.getHolder();
CreativeContentPacket pk = new CreativeContentPacket();
if (!p.isSpectator()) { //fill it for all gamemodes except spectator
pk.entries = Item.getCreativeItems().toArray(Item.EMPTY_ARRAY);
}
p.dataPacket(pk);
}
//由于NK从PlayerInventory中分离了盔甲栏,并且getSize值修改为36,但实际上slots最大容量为40,按照逻辑应该将solts size也减4
@Override
public int getFreeSpace(Item item) {
int maxStackSize = Math.min(item.getMaxStackSize(), this.getMaxStackSize());
int slots = this.slots.size() > 36 ? this.slots.size() - 4 : this.slots.size();
int space = (this.getSize() - slots) * maxStackSize;
for (Item slot : this.getContents().values()) {
if (slot == null || slot.getId() == 0) {
space += maxStackSize;
continue;
}
if (slot.equals(item, true, true)) {
space += maxStackSize - slot.getCount();
}
}
return space;
}
@Override
public EntityHuman getHolder() {
return (EntityHuman) super.getHolder();
}
@Override
public void onOpen(Player who) {
super.onOpen(who);
if (who.spawned) {
ContainerOpenPacket pk = new ContainerOpenPacket();
pk.windowId = who.getWindowId(this);
pk.type = this.getType().getNetworkType();
pk.x = who.getFloorX();
pk.y = who.getFloorY();
pk.z = who.getFloorZ();
pk.entityId = who.getId();
who.dataPacket(pk);
}
}
@Override
public void onClose(Player who) {
ContainerClosePacket pk = new ContainerClosePacket();
pk.windowId = who.getWindowId(this);
pk.wasServerInitiated = who.getClosingWindowId() != pk.windowId;
who.dataPacket(pk);
// player can never stop viewing their own inventory
if (who != holder) {
super.onClose(who);
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy