/*
* Project: UHC
* Class: gg.uhc.uhc.inventory.IconInventory
*
* The MIT License (MIT)
*
* Copyright (c) 2015 Graham Howden <graham_howden1 at yahoo.co.uk>.
*
* 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 gg.uhc.uhc.inventory;
import gg.uhc.uhc.ShutdownRegistry;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class IconInventory implements IconUpdateListener, Listener, ShutdownRegistry.ShutdownListener {
protected static final int INVENTORY_WIDTH = 9;
protected final List<IconStack> icons = Lists.newArrayList();
protected final Set<Inventory> openedInventories = Sets.newHashSet();
protected final String title;
public IconInventory(String title) {
this.title = title;
ShutdownRegistry.addListener(this);
}
public void showTo(HumanEntity entity) {
// how many icons do we want to show
final int iconCount = icons.size();
// how many slots are required, in increments of 9, min 9, max 54
final int slotsRequired = Math.max(
9,
Math.min(
54,
INVENTORY_WIDTH * ((iconCount + INVENTORY_WIDTH - 1) / INVENTORY_WIDTH)
)
);
// Create and render inventory
final Inventory inventory = Bukkit.createInventory(null, slotsRequired, title);
final ItemStack[] contents = new ItemStack[slotsRequired];
for (int i = 0; i < icons.size(); i++) {
contents[i] = icons.get(i);
}
inventory.setContents(contents);
// Show to player
entity.openInventory(inventory);
openedInventories.add(inventory);
}
public void registerNewIcon(IconStack icon) {
icon.registerUpdateHandler(this);
add(icon);
}
protected int add(IconStack icon) {
// check where to insert and
// add item to list in the correct location
final int index = indexToInsert(icon);
icons.add(index, icon);
reopenForCurrentViewers();
return index;
}
protected int indexToInsert(IconStack icon) {
int insertionIndex = Collections.binarySearch(icons, icon);
// weight wasn't found so it returns (-(insertion index) -1)
if (insertionIndex < 0) {
insertionIndex = -(insertionIndex + 1);
}
return insertionIndex;
}
protected Collection<HumanEntity> getCurrentViewers() {
final List<HumanEntity> viewers = Lists.newArrayList();
for (final Inventory openedInventory : openedInventories) {
viewers.addAll(openedInventory.getViewers());
}
return viewers;
}
protected void reopenForCurrentViewers() {
for (final HumanEntity viewer : getCurrentViewers()) {
viewer.closeInventory();
showTo(viewer);
}
}
@Override
public void onUpdate(IconStack icon) {
final int index = icons.indexOf(icon);
// this isn't one of our icons
if (index < 0) return;
// refresh the item
for (final Inventory openedInventory : openedInventories) {
openedInventory.setItem(index, icon);
}
}
@Override
public void onWeightUpdate(IconStack icon) {
final int index = icons.indexOf(icon);
// this isn't one of our icons
if (index < 0) return;
// remove from the list
icons.remove(index);
reopenForCurrentViewers();
// readd to the list
final int newIndex = add(icon);
}
@EventHandler(ignoreCancelled = true)
public void on(InventoryClickEvent event) {
final Inventory inventory = event.getInventory();
if (!inventory.getTitle().equals(title)) return;
event.setCancelled(true);
final int slot = event.getRawSlot();
if (slot < 0 || slot >= inventory.getSize() || slot >= icons.size()) return;
// call event
final IconStack icon = icons.get(slot);
if (icon != null) {
icon.onClick((Player) event.getWhoClicked());
}
}
@EventHandler
public void on(InventoryDragEvent event) {
final Inventory inventory = event.getInventory();
if (!inventory.getTitle().equals(title)) return;
event.setCancelled(true);
}
@EventHandler
public void on(InventoryCloseEvent event) {
openedInventories.remove(event.getInventory());
}
@Override
public void onPluginShutdown() {
for (final HumanEntity viewer : getCurrentViewers()) {
viewer.closeInventory();
}
openedInventories.clear();
}
}