Java tutorial
/* * The MIT License (MIT) * * Copyright (c) 2016. Diorite (by Bartomiej Mazur (aka GotoFinal)) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.diorite.impl.inventory; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Objects; import java.util.Set; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; import org.diorite.impl.connection.packets.play.clientbound.PacketPlayClientboundSetSlot; import org.diorite.impl.entity.IPlayer; import org.diorite.impl.inventory.item.ItemStackImpl; import org.diorite.impl.inventory.item.ItemStackImplArray; import org.diorite.entity.Human; import org.diorite.inventory.Inventory; import org.diorite.inventory.InventoryHolder; import org.diorite.inventory.item.ItemStack; import org.diorite.material.Material; import org.diorite.utils.collections.arrays.DioriteArrayUtils; import org.diorite.utils.collections.sets.ConcurrentSet; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntCollection; import it.unimi.dsi.fastutil.shorts.ShortCollection; import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet; public abstract class InventoryImpl<T extends InventoryHolder> implements Inventory { protected final T holder; protected final Set<Human> viewers = new ConcurrentSet<>(5, 0.2f, 6); protected String title; protected InventoryImpl(final T holder) { this.holder = holder; } @Override public ItemStack[] getContents() { return this.getArray().toArray(new ItemStack[this.getArray().length()]); } /** * Returns raw atomic array with contents of eq. * * @return raw atomic array with contents of eq. */ public abstract ItemStackImplArray getArray(); // public abstract void softUpdate(); final ShortCollection notNullItems = new ShortOpenHashSet(50, .2f); // used only for updates public boolean softUpdate() { final ItemStackImpl[] items = this.getArray().toArray(new ItemStackImpl[this.getArray().length()]); final Set<PacketPlayClientboundSetSlot> packets = new HashSet<>(items.length); for (short i = 0, itemsLength = (short) items.length; i < itemsLength; i++) { final ItemStackImpl item = items[i]; if (item != null) { if ((item.getAmount() == 0) || (Material.AIR.simpleEquals(item.getMaterial()))) { this.replace(i, item, null); packets.add(new PacketPlayClientboundSetSlot(this.getWindowId(), i, null)); continue; } this.notNullItems.add(i); if (item.setClean()) // returns true if item was dirty before cleaning { packets.add(new PacketPlayClientboundSetSlot(this.getWindowId(), i, item)); } } else if (this.notNullItems.remove(i)) { packets.add(new PacketPlayClientboundSetSlot(this.getWindowId(), i, null)); } } if (!packets.isEmpty()) { final PacketPlayClientboundSetSlot[] packetsArray = packets .toArray(new PacketPlayClientboundSetSlot[packets.size()]); this.viewers.stream().filter(h -> h instanceof IPlayer).map(h -> (IPlayer) h) .forEach(p -> p.getNetworkManager().sendPackets(packetsArray)); return true; } return false; } /** * Completely replaces the inventory's contents. Removes all existing * contents and replaces it with the IItemStacks given in the array. * * @param items A complete replacement for the contents; the length must * be less than or equal to {@link #size()}. * * @throws IllegalArgumentException If the array has more items than the * inventory. */ public void setContent(final ItemStackImplArray items) { final ItemStackImplArray content = this.getArray(); for (int i = 0, size = content.length(); i < size; i++) { content.set(i, items.getOrNull(i)); } } public void setContent(final ItemStackImpl[] items) { final ItemStackImplArray content = this.getArray(); for (int i = 0, size = content.length(); i < size; i++) { content.set(i, (i >= items.length) ? null : items[i]); } } @Override public void setContent(final ItemStack[] items) { final ItemStackImplArray content = this.getArray(); for (int i = 0, size = content.length(); i < size; i++) { content.set(i, (i >= items.length) ? null : ItemStackImpl.wrap(items[i])); } } @Override public int remove(final ItemStack itemStack) { final ItemStackImplArray content = this.getArray(); if (itemStack == null) { return -1; } for (int i = 0, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if (Objects.equals(item, itemStack)) { content.compareAndSet(i, ItemStackImpl.wrap(item), null); return i; } } return -1; } @Override public int[] removeAll(final ItemStack itemStack) { final ItemStackImplArray content = this.getArray(); if (itemStack == null) { return DioriteArrayUtils.EMPTY_INTS; } final IntCollection list = new IntArrayList(10); for (int i = 0, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if (Objects.equals(item, itemStack)) { content.compareAndSet(i, ItemStackImpl.wrap(item), null); list.add(i); } } if (list.isEmpty()) { return DioriteArrayUtils.EMPTY_INTS; } return list.toIntArray(); } @Override public int remove(final Material material, final boolean ignoreType) { final ItemStackImplArray content = this.getArray(); if (material == null) { return -1; } for (int i = 0, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if (item == null) { continue; } final Material mat = item.getMaterial(); if (ignoreType) { if ((material.ordinal() != mat.ordinal())) { continue; } } else if (!Objects.equals(mat, material)) { continue; } content.compareAndSet(i, ItemStackImpl.wrap(item), null); return i; } return -1; } @Override public int[] removeAll(final Material material, final boolean ignoreType) { final ItemStackImplArray content = this.getArray(); if (material == null) { return DioriteArrayUtils.EMPTY_INTS; } final IntCollection list = new IntArrayList(10); for (int i = 0, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if (item == null) { continue; } final Material mat = item.getMaterial(); if (ignoreType) { if ((material.ordinal() != mat.ordinal())) { continue; } } else if (!Objects.equals(mat, material)) { continue; } content.compareAndSet(i, ItemStackImpl.wrap(item), null); list.add(i); } if (list.isEmpty()) { return DioriteArrayUtils.EMPTY_INTS; } return list.toIntArray(); } @Override public int removeFromEnd(final ItemStack itemStack) { final ItemStackImplArray content = this.getArray(); if (itemStack == null) { return -1; } for (int i = content.length() - 1; i >= 0; i--) { final ItemStack item = content.get(i); if (Objects.equals(item, itemStack)) { content.compareAndSet(i, ItemStackImpl.wrap(item), null); return i; } } return -1; } @Override public int[] removeAllFromEnd(final ItemStack itemStack) { final ItemStackImplArray content = this.getArray(); if (itemStack == null) { return DioriteArrayUtils.EMPTY_INTS; } final IntCollection list = new IntArrayList(10); for (int i = content.length() - 1; i >= 0; i--) { final ItemStack item = content.get(i); if (Objects.equals(item, itemStack)) { content.compareAndSet(i, ItemStackImpl.wrap(item), null); list.add(i); } } if (list.isEmpty()) { return DioriteArrayUtils.EMPTY_INTS; } return list.toIntArray(); } @Override public int removeFromEnd(final Material material, final boolean ignoreType) { final ItemStackImplArray content = this.getArray(); if (material == null) { return -1; } for (int i = content.length() - 1; i >= 0; i--) { final ItemStack item = content.get(i); if (item == null) { continue; } final Material mat = item.getMaterial(); if (ignoreType) { if ((material.ordinal() != mat.ordinal())) { continue; } } else if (!Objects.equals(mat, material)) { continue; } content.compareAndSet(i, ItemStackImpl.wrap(item), null); return i; } return -1; } @Override public int[] removeAllFromEnd(final Material material, final boolean ignoreType) { final ItemStackImplArray content = this.getArray(); if (material == null) { return DioriteArrayUtils.EMPTY_INTS; } final IntCollection list = new IntArrayList(10); for (int i = content.length() - 1; i >= 0; i--) { final ItemStack item = content.get(i); if (item == null) { continue; } final Material mat = item.getMaterial(); if (ignoreType) { if ((material.ordinal() != mat.ordinal())) { continue; } } else if (!Objects.equals(mat, material)) { continue; } content.compareAndSet(i, ItemStackImpl.wrap(item), null); list.add(i); } if (list.isEmpty()) { return DioriteArrayUtils.EMPTY_INTS; } return list.toIntArray(); } @Override public int replace(final ItemStack excepted, final ItemStack newItem) throws IllegalArgumentException { ItemStackImpl.validate(excepted); final ItemStackImplArray content = this.getArray(); for (int i = 0, size = content.length(); i < size; i++) { if (content.compareAndSet(i, (ItemStackImpl) excepted, ItemStackImpl.wrap(newItem))) { return i; } } return -1; } @Override public int replaceFromEnd(final ItemStack excepted, final ItemStack newItem) throws IllegalArgumentException { ItemStackImpl.validate(excepted); final ItemStackImplArray content = this.getArray(); for (int i = content.length() - 1; i >= 0; i--) { if (content.compareAndSet(i, (ItemStackImpl) excepted, ItemStackImpl.wrap(newItem))) { return i; } } return -1; } @Override public boolean replace(final int slot, final ItemStack excepted, final ItemStack newItem) throws IllegalArgumentException { ItemStackImpl.validate(excepted); return this.getArray().compareAndSet(slot, (ItemStackImpl) excepted, ItemStackImpl.wrap(newItem)); } @Override public ItemStackImpl getItem(final int index) { return this.getArray().get(index); } @Override public ItemStackImpl setItem(final int index, final ItemStack item) { return this.getArray().getAndSet(index, ItemStackImpl.wrap(item)); } @Override public Map<Integer, ? extends ItemStack> all(final Material material, final boolean ignoreType) { final ItemStackImplArray content = this.getArray(); final Map<Integer, ItemStack> slots = new HashMap<>(10); for (int i = 0, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if (item != null) { if (ignoreType) { if (item.getMaterial().isThisSameID(material)) { slots.put(i, item); } } else if (item.getMaterial().equals(material)) { slots.put(i, item); } } } return slots; } @Override public HashMap<Integer, ? extends ItemStack> all(final ItemStack item) { final ItemStackImplArray content = this.getArray(); final HashMap<Integer, ItemStack> slots = new HashMap<>(10); if (item != null) { for (int i = 0, size = content.length(); i < size; i++) { final ItemStack itemStack = content.get(i); if (item.equals(itemStack)) { slots.put(i, itemStack); } } } return slots; } @Override public int first(final Material material) { return this.first(material, 0); } @Override public int first(final Material material, final int startIndex) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if ((item != null) && (item.getMaterial().equals(material))) { return i; } } return -1; } @Override public int first(final ItemStack item, final boolean withAmount) { return this.first(item, 0, withAmount); } @Override public int first(final ItemStack item, final int startIndex, final boolean withAmount) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex, size = content.length(); i < size; i++) { final ItemStack itemStack = content.get(i); //noinspection ObjectEquality if (item == itemStack) { return i; } if (item == null) { continue; } if (itemStack != null) { if (withAmount ? item.equals(itemStack) : item.isSimilar(itemStack)) { return i; } } } return -1; } @Override public int firstNotFull(final Material material) { return this.firstNotFull(material, 0); } @Override public int firstNotFull(final Material material, final int startIndex) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex, size = content.length(); i < size; i++) { final ItemStack item = content.get(i); if ((item != null) && (item.getMaterial().equals(material)) && (item.getAmount() < material.getMaxStack())) { return i; } } return -1; } @Override public int firstNotFull(final ItemStack item, final boolean withAmount) { return this.firstNotFull(item, 0, withAmount); } @Override public int firstNotFull(final ItemStack item, final int startIndex, final boolean withAmount) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex, size = content.length(); i < size; i++) { final ItemStack itemStack = content.get(i); //noinspection ObjectEquality if (item == itemStack) { return i; } if (item == null) { continue; } if (itemStack != null) { if (withAmount) { if (item.equals(itemStack) && ((item.getAmount() + itemStack.getAmount()) < itemStack .getMaterial().getMaxStack())) { return i; } } else if (item.isSimilar(itemStack)) { return i; } } } return -1; } @Override public int firstEmpty() { final ItemStackImplArray content = this.getArray(); for (int i = 0, size = content.length(); i < size; i++) { final ItemStack itemStack = content.get(i); if (itemStack == null) { return i; } } return -1; } @Override public int last(final Material material) { return this.last(material, this.size() - 1); } @Override public int last(final Material material, final int startIndex) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex; i >= 0; i--) { final ItemStack item = content.get(i); if ((item != null) && (item.getMaterial().equals(material))) { return i; } } return -1; } @Override public int last(final ItemStack item, final boolean withAmount) { return this.last(item, this.size() - 1, withAmount); } @Override public int last(final ItemStack item, final int startIndex, final boolean withAmount) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex; i >= 0; i--) { final ItemStack itemStack = content.get(i); //noinspection ObjectEquality if (item == itemStack) { return i; } if (itemStack != null) { if (withAmount ? item.equals(itemStack) : item.isSimilar(itemStack)) { return i; } } } return -1; } @Override public int lastNotFull(final Material material) { return this.lastNotFull(material, this.size() - 1); } @Override public int lastNotFull(final Material material, final int startIndex) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex; i >= 0; i--) { final ItemStack item = content.get(i); if ((item != null) && (item.getMaterial().equals(material)) && (item.getAmount() < material.getMaxStack())) { return i; } } return -1; } @Override public int lastNotFull(final ItemStack item, final boolean withAmount) { return this.lastNotFull(item, this.size() - 1, withAmount); } @Override public int lastNotFull(final ItemStack item, final int startIndex, final boolean withAmount) { final ItemStackImplArray content = this.getArray(); for (int i = startIndex; i >= 0; i--) { final ItemStack itemStack = content.get(i); //noinspection ObjectEquality if (item == itemStack) { return i; } if (itemStack != null) { if (withAmount) { if (item.equals(itemStack) && ((item.getAmount() + itemStack.getAmount()) < itemStack .getMaterial().getMaxStack())) { return i; } } else if (item.isSimilar(itemStack)) { return i; } } } return -1; } @Override public int lastEmpty() { final ItemStackImplArray content = this.getArray(); for (int i = content.length() - 1; i >= 0; i--) { final ItemStack itemStack = content.get(i); if (itemStack == null) { return i; } } return -1; } @Override public void clear(final int index) { this.getArray().set(index, null); } @Override public void clear() { final ItemStackImplArray content = this.getArray(); for (int i = 0, size = content.length(); i < size; i++) { content.set(i, null); } } @Override public int size() { return this.getArray().length(); } @Override public Set<? extends Human> getViewers() { return this.viewers; } @Override public String getTitle() { return this.title; } @Override public void setTitle(final String str) { this.title = str; this.update(); } @Override public T getHolder() { return this.holder; } @Override public InventoryIterator iterator() { return new InventoryIterator(this); } @Override public String toString() { return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).appendSuper(super.toString()) .append("title", this.title).toString(); } }