Large Update

Added new Hopper filtering mechanic.
Config now saves in Async.
Fixed Inventory sorter removing item meta.
This commit is contained in:
jameslfc19 2020-04-27 21:54:35 +01:00
parent 96a23c3d7e
commit df23078d80
18 changed files with 213 additions and 123 deletions

View File

@ -6,7 +6,7 @@
<groupId>com.jamesdpeters.chests</groupId>
<artifactId>ChestsPlusPlus</artifactId>
<version>1.0-SNAPSHOT</version>
<version>1.15 v1.4-DEV</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>

View File

@ -4,7 +4,7 @@ import com.jamesdpeters.minecraft.chests.commands.RemoteChestCommand;
import com.jamesdpeters.minecraft.chests.listeners.ChestLinkListener;
import com.jamesdpeters.minecraft.chests.listeners.HopperListener;
import com.jamesdpeters.minecraft.chests.listeners.InventoryListener;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.misc.Permissions;
import com.jamesdpeters.minecraft.chests.misc.Settings;
import com.jamesdpeters.minecraft.chests.misc.Stats;
@ -37,7 +37,7 @@ import org.bukkit.plugin.java.annotation.plugin.author.Author;
@Permission(name = Permissions.OPEN, desc = "Gives permission to open ChestLinks!", defaultValue = PermissionDefault.TRUE)
@Permission(name = Permissions.MENU, desc = "Gives permission to open the ChestLink menu!", defaultValue = PermissionDefault.TRUE)
@Permission(name = Permissions.REMOVE, desc = "Gives permission to remove a ChestLink!", defaultValue = PermissionDefault.TRUE)
@Permission(name = Permissions.OPEN_ANY, desc = "Gives permission to open all chests, for admin use.", defaultValue = PermissionDefault.OP)
@Permission(name = Permissions.OPEN_ANY, desc = "Gives permission to open all chests, for admin use.", defaultValue = PermissionDefault.FALSE)
@Permission(name = Permissions.MEMBER, desc = "Gives permission to add/remove a member to/from their chestlink.", defaultValue = PermissionDefault.TRUE)
@Permission(name = Permissions.SORT, desc = "Set the sorting option for the given ChestLink.", defaultValue = PermissionDefault.TRUE)
public class ChestsPlusPlus extends JavaPlugin {

View File

@ -1,7 +1,7 @@
package com.jamesdpeters.minecraft.chests.commands;
import com.jamesdpeters.minecraft.chests.inventories.ChestLinkMenu;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.misc.Messages;
import com.jamesdpeters.minecraft.chests.misc.Permissions;
import com.jamesdpeters.minecraft.chests.misc.Utils;
@ -14,7 +14,6 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.swing.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

View File

@ -1,10 +1,9 @@
package com.jamesdpeters.minecraft.chests.containers;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.UUID;

View File

@ -0,0 +1,26 @@
package com.jamesdpeters.minecraft.chests.filters;
import org.bukkit.inventory.ItemStack;
public class Filter {
private ItemStack filter;
private boolean filterByItemMeta = true;
public Filter(ItemStack filter, boolean filterByItemMeta){
this.filter = filter;
this.filterByItemMeta = filterByItemMeta;
}
public ItemStack getFilter() {
return filter;
}
public boolean isFiltered(ItemStack itemStack){
if(filter.isSimilar(itemStack)) return true;
if(!filterByItemMeta){
if(filter.getType().equals(itemStack.getType())) return true;
}
return false;
}
}

View File

@ -0,0 +1,45 @@
package com.jamesdpeters.minecraft.chests.filters;
import org.bukkit.Rotation;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class HopperFilter {
public static boolean isInFilter(List<Filter> filters, ItemStack item){
if(filters == null) return true;
if(filters.size() == 0) return true;
for(Filter filter : filters){
if(filter.isFiltered(item)) return true;
}
return false;
}
public static List<Filter> getHopperFilters(Block block){
Collection<Entity> ent = block.getLocation().getWorld().getNearbyEntities(block.getLocation(),1.01,1.01,1.01);
List<Filter> filters = new ArrayList<>(ent.size());
for(Entity entity : ent){
if(entity instanceof ItemFrame){
ItemFrame frame = (ItemFrame) entity;
Block attachedBlock = frame.getLocation().getBlock().getRelative(frame.getAttachedFace());
if(block.equals(attachedBlock)){
boolean isFilteredByItemMeta = true;
Rotation rotation = frame.getRotation();
if(rotation.equals(Rotation.FLIPPED)) isFilteredByItemMeta = false;
filters.add(new Filter(frame.getItem(),isFilteredByItemMeta));
}
}
}
return filters;
}
public static boolean isInFilter(Block block, ItemStack itemStack){
return isInFilter(getHopperFilters(block),itemStack);
}
}

View File

@ -1,7 +1,7 @@
package com.jamesdpeters.minecraft.chests.inventories;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import fr.minuskube.inv.ClickableItem;
@ -9,7 +9,6 @@ import fr.minuskube.inv.SmartInventory;
import fr.minuskube.inv.content.InventoryContents;
import fr.minuskube.inv.content.InventoryProvider;
import fr.minuskube.inv.content.Pagination;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

View File

@ -3,6 +3,7 @@ package com.jamesdpeters.minecraft.chests.listeners;
import com.jamesdpeters.minecraft.chests.containers.ChestLinkInfo;
import com.jamesdpeters.minecraft.chests.misc.*;
import com.jamesdpeters.minecraft.chests.runnables.ChestLinkVerifier;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import org.bukkit.ChatColor;
import org.bukkit.block.Block;

View File

@ -1,24 +1,24 @@
package com.jamesdpeters.minecraft.chests.listeners;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.filters.HopperFilter;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import org.bukkit.Material;
import org.bukkit.ChatColor;
import org.bukkit.Rotation;
import org.bukkit.block.Block;
import org.bukkit.block.Hopper;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.ItemFrame;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryMoveItemEvent;
import org.bukkit.event.inventory.InventoryPickupItemEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Collection;
public class HopperListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
@ -28,7 +28,7 @@ public class HopperListener implements Listener {
if(event.getDestination().getLocation() != null){
if(event.getDestination().getLocation().getBlock().isBlockPowered()) return;
}
event.setCancelled(!isItemInFilter(event.getDestination().getLocation().getBlock(),event.getItem()));
event.setCancelled(!HopperFilter.isInFilter(event.getDestination().getLocation().getBlock(),event.getItem()));
}
}
@ -56,28 +56,51 @@ public class HopperListener implements Listener {
@EventHandler
public void onHopperPickup(InventoryPickupItemEvent event){
if(event.getInventory().getHolder() instanceof Hopper){
event.setCancelled(!isItemInFilter(event.getInventory().getLocation().getBlock(),event.getItem().getItemStack()));
event.setCancelled(!HopperFilter.isInFilter(event.getInventory().getLocation().getBlock(), event.getItem().getItemStack()));
}
}
public static boolean isItemInFilter(Block block, ItemStack item){
Collection<Entity> ent = block.getLocation().getWorld().getNearbyEntities(block.getLocation(),1.01,1.01,1.01);
boolean hasFilter = false;
for(Entity frame : ent){
if(frame instanceof ItemFrame){
Block attachedBlock = frame.getLocation().getBlock().getRelative(((ItemFrame) frame).getAttachedFace());
if(block.equals(attachedBlock)){
if(((ItemFrame) frame).getItem().getType() != Material.AIR) hasFilter = true;
if(item.isSimilar(((ItemFrame) frame).getItem())){
return true;
}
}
@EventHandler
public void itemFrameInteract(PlayerInteractEntityEvent event){
if(event.getRightClicked().getType().equals(EntityType.ITEM_FRAME)){
ItemFrame itemFrame = (ItemFrame) event.getRightClicked();
Block attachedBlock = itemFrame.getLocation().getBlock().getRelative(((ItemFrame) itemFrame).getAttachedFace());
if(!(attachedBlock.getState() instanceof Hopper)) return;
Rotation rotation = itemFrame.getRotation().rotateClockwise();
if(rotation.equals(Rotation.FLIPPED)){
event.getPlayer().sendMessage(ChatColor.AQUA+"ItemFrame now filters all types of this item! e.g Enchanted Books.");
} else if(rotation.equals(Rotation.FLIPPED_45)) {
event.getPlayer().sendMessage(ChatColor.GREEN+"ItemFrame is in default filtering mode.");
}
}
if(!hasFilter) return true;
return false;
}
// public static boolean isItemInFilter(Block block, ItemStack item){
// Bukkit.broadcastMessage("Cheking item: "+item.getType().name());
// Collection<Entity> ent = block.getLocation().getWorld().getNearbyEntities(block.getLocation(),1.01,1.01,1.01);
// boolean hasFilter = false;
// for(Entity entity : ent){
// if(entity instanceof ItemFrame){
// ItemFrame frame = (ItemFrame) entity;
// Block attachedBlock = frame.getLocation().getBlock().getRelative(frame.getAttachedFace());
// if(block.equals(attachedBlock)){
// ItemStack itemStack = frame.getItem();
// Bukkit.broadcastMessage("Item Filter!");
// if(itemStack.getType() != Material.AIR) hasFilter = true;
// if(item.isSimilar(itemStack)){
// return true;
// }
// Rotation rotation = frame.getRotation();
// Bukkit.broadcastMessage("Frame rotation: "+rotation.toString());
// if(rotation.equals(Rotation.FLIPPED)){
// if(item.getType().equals(itemStack.getType())) return true;
// }
// }
// }
// }
// return !hasFilter;
// }
}

View File

@ -1,7 +1,7 @@
package com.jamesdpeters.minecraft.chests.listeners;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.misc.Messages;
import com.jamesdpeters.minecraft.chests.misc.Permissions;
import com.jamesdpeters.minecraft.chests.misc.Utils;
@ -14,7 +14,6 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.*;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.scheduler.BukkitScheduler;
public class InventoryListener implements Listener {

View File

@ -1,13 +1,10 @@
package com.jamesdpeters.minecraft.chests.misc;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
public class Messages {
private static String TAG = "[Chests++]";

View File

@ -1,9 +1,7 @@
package com.jamesdpeters.minecraft.chests.misc;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import java.util.concurrent.Callable;
public class Stats {

View File

@ -2,16 +2,16 @@ package com.jamesdpeters.minecraft.chests.misc;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.containers.ChestLinkInfo;
import com.jamesdpeters.minecraft.chests.filters.Filter;
import com.jamesdpeters.minecraft.chests.filters.HopperFilter;
import com.jamesdpeters.minecraft.chests.runnables.ChestLinkVerifier;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import com.jamesdpeters.minecraft.chests.sort.InventorySorter;
import org.apache.commons.lang.StringUtils;
import org.bukkit.*;
import org.bukkit.block.*;
import org.bukkit.block.data.Directional;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.block.SignChangeEvent;
@ -100,11 +100,11 @@ public class Utils {
//player.closeInventory();
}
public static ItemStack removeStackFromInventory(Inventory inventory, int amount, List<ItemStack> filters){
public static ItemStack removeStackFromInventory(Inventory inventory, int amount, List<Filter> filters){
ItemStack toRemove;
for(int i=0; i<inventory.getContents().length; i++){
ItemStack stack = inventory.getItem(i);
if((stack != null) && (isInFilter(filters,stack))){
if((stack != null) && (HopperFilter.isInFilter(filters,stack))){
toRemove = stack.clone();
toRemove.setAmount(Math.min(stack.getAmount(),amount));
stack.setAmount(stack.getAmount()-toRemove.getAmount());
@ -114,7 +114,7 @@ public class Utils {
return null;
}
public static boolean moveToOtherInventory(Inventory from, int amount, Inventory to, List<ItemStack> filters){
public static boolean moveToOtherInventory(Inventory from, int amount, Inventory to, List<Filter> filters){
ItemStack removed = removeStackFromInventory(from,amount,filters);
if(removed != null) {
HashMap<Integer, ItemStack> leftOvers = to.addItem(removed);
@ -203,49 +203,26 @@ public class Utils {
}
}
public static List<ItemStack> hasFilter(Block block){
List<ItemStack> filters = new ArrayList<>();
addIfNotNull(filters,getFilter(block,1,0));
addIfNotNull(filters,getFilter(block,-1,0));
addIfNotNull(filters,getFilter(block,0,1));
addIfNotNull(filters,getFilter(block,0,-1));
return filters;
}
private static ItemStack getFilter(Block block, int xOffset, int zOffset){
Block frame = block.getRelative(xOffset, 0,zOffset);
if(frame.getState() instanceof ItemFrame){
return ((ItemFrame) frame.getState()).getItem();
}
return null;
}
private static <T> void addIfNotNull(List<T> list, T element){
if(element != null) list.add(element);
}
public static boolean isInFilter(List<ItemStack> filters, ItemStack item){
if(filters == null) return true;
if(filters.size() == 0) return true;
for(ItemStack filter : filters){
if(filter.isSimilar(item)) return true;
}
return false;
}
public static List<ItemStack> getHopperFilters(Block block){
Collection<Entity> ent = block.getLocation().getWorld().getNearbyEntities(block.getLocation(),1.01,1.01,1.01);
List<ItemStack> filters = new ArrayList<>();
for(Entity frame : ent){
if(frame instanceof ItemFrame){
Block attachedBlock = frame.getLocation().getBlock().getRelative(((ItemFrame) frame).getAttachedFace());
if(block.equals(attachedBlock)){
filters.add(((ItemFrame) frame).getItem());
}
}
}
return filters;
}
// public static List<ItemStack> hasFilter(Block block){
// List<ItemStack> filters = new ArrayList<>();
// addIfNotNull(filters,getFilter(block,1,0));
// addIfNotNull(filters,getFilter(block,-1,0));
// addIfNotNull(filters,getFilter(block,0,1));
// addIfNotNull(filters,getFilter(block,0,-1));
// return filters;
// }
//
// private static ItemStack getFilter(Block block, int xOffset, int zOffset){
// Block frame = block.getRelative(xOffset, 0,zOffset);
// if(frame.getState() instanceof ItemFrame){
// return ((ItemFrame) frame.getState()).getItem();
// }
// return null;
// }
//
// private static <T> void addIfNotNull(List<T> list, T element){
// if(element != null) list.add(element);
// }
public static ItemStack getNamedItem(ItemStack item, String name){
ItemMeta meta = item.getItemMeta();

View File

@ -1,7 +1,7 @@
package com.jamesdpeters.minecraft.chests.runnables;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.serialize.Config;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import org.bukkit.Location;
import org.bukkit.block.Block;

View File

@ -1,6 +1,7 @@
package com.jamesdpeters.minecraft.chests.runnables;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.filters.HopperFilter;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import org.bukkit.Location;
@ -35,7 +36,7 @@ public class VirtualChestToHopper extends BukkitRunnable {
if(below.getBlock().isBlockIndirectlyPowered()|| below.getBlock().isBlockPowered()){
continue;
}
Utils.moveToOtherInventory(storage.getInventory(), 1, hopper.getInventory(), Utils.getHopperFilters(below.getBlock()));
Utils.moveToOtherInventory(storage.getInventory(), 1, hopper.getInventory(), HopperFilter.getHopperFilters(below.getBlock()));
storage.sort();
}
}

View File

@ -1,6 +1,9 @@
package com.jamesdpeters.minecraft.chests.misc;
package com.jamesdpeters.minecraft.chests.serialize;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.containers.ChestLinkInfo;
import com.jamesdpeters.minecraft.chests.misc.Messages;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.serialize.InventoryStorage;
import com.jamesdpeters.minecraft.chests.serialize.LinkedChest;
import org.bukkit.Bukkit;
@ -12,6 +15,8 @@ import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitScheduler;
import java.io.File;
import java.io.IOException;
@ -22,26 +27,33 @@ import java.util.stream.Collectors;
public class Config {
private static LinkedChest store;
private static FileConfiguration config;
public Config(){
try {
FileConfiguration configuration = YamlConfiguration.loadConfiguration(new File("chests.yml"));
store = (LinkedChest) configuration.get("chests++", new HashMap<String, HashMap<String, List<Location>>>());
config = YamlConfiguration.loadConfiguration(new File("chests.yml"));
store = (LinkedChest) config.get("chests++", new HashMap<String, HashMap<String, List<Location>>>());
} catch (Exception e){
store = new LinkedChest();
save();
}
}
public static void save(){
FileConfiguration config = new YamlConfiguration();
config.set("chests++", store);
try {
config.save("chests.yml");
} catch (IOException e) {
e.printStackTrace();
private static BukkitRunnable saveRunnable = new BukkitRunnable(){
@Override
public void run() {
if(config == null) config = new YamlConfiguration();
config.set("chests++", store);
try{
config.save("chests.yml");
} catch (IOException e) {
e.printStackTrace();
}
}
};
public static void save(){
saveRunnable.runTaskAsynchronously(ChestsPlusPlus.PLUGIN);
}
public static List<InventoryStorage> getInventoryStorageMemberOf(Player player){

View File

@ -3,7 +3,6 @@ package com.jamesdpeters.minecraft.chests.serialize;
import com.jamesdpeters.minecraft.chests.ChestsPlusPlus;
import com.jamesdpeters.minecraft.chests.interfaces.VirtualInventoryHolder;
import com.jamesdpeters.minecraft.chests.inventories.ChestLinkMenu;
import com.jamesdpeters.minecraft.chests.misc.Config;
import com.jamesdpeters.minecraft.chests.misc.Permissions;
import com.jamesdpeters.minecraft.chests.misc.Utils;
import com.jamesdpeters.minecraft.chests.runnables.VirtualChestToHopper;
@ -150,10 +149,10 @@ public class InventoryStorage implements ConfigurationSerializable {
}
public ItemStack getIventoryIcon(Player player){
Material mostCommon = InventorySorter.getMostCommonItem(inventory);
ItemStack mostCommon = InventorySorter.getMostCommonItem(inventory);
ItemStack toReturn;
if(mostCommon == null) toReturn = new ItemStack(Material.CHEST);
else toReturn = new ItemStack(mostCommon);
else toReturn = mostCommon.clone();
ItemMeta meta = toReturn.getItemMeta();
if(meta != null) {

View File

@ -1,12 +1,14 @@
package com.jamesdpeters.minecraft.chests.sort;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class InventorySorter {
@ -38,14 +40,19 @@ public class InventorySorter {
private static void sortByAmount(Inventory inventory, boolean descending){
HashMap<Material,Integer> itemAmounts = getItemAmounts(inventory.getContents());
HashMap<ItemStack,Integer> itemAmounts = getItemAmounts(inventory.getContents());
List<ItemStack> condensed = condenseInventory(inventory.getContents());
condensed.sort((item1, item2) -> {
if (item1 == null) return 1;
if (item2 == null) return -1;
int itemOrder = itemAmounts.get(item1.getType()).compareTo(itemAmounts.get(item2.getType()));
Optional<ItemStack> matchItem1 = itemAmounts.keySet().stream().filter(is -> is.isSimilar(item1)).findFirst();
Optional<ItemStack> matchItem2 = itemAmounts.keySet().stream().filter(is -> is.isSimilar(item2)).findFirst();
if(!matchItem1.isPresent()) return 1;
if(!matchItem2.isPresent()) return -1;
int itemOrder = itemAmounts.get(matchItem1.get()).compareTo(itemAmounts.get(matchItem2.get()));
if(descending) itemOrder *= -1;
return itemOrder;
});
@ -53,45 +60,53 @@ public class InventorySorter {
inventory.setContents(itemStacks);
}
private static HashMap<Material,Integer> getItemAmounts(ItemStack[] itemStacks){
HashMap<Material,Integer> itemAmounts = new HashMap<>();
private static HashMap<ItemStack,Integer> getItemAmounts(ItemStack[] itemStacks){
HashMap<ItemStack,Integer> itemAmounts = new HashMap<>();
for(ItemStack itemStack : itemStacks){
if(itemStack == null) continue;
int amount;
if(!itemAmounts.containsKey(itemStack.getType())){
Optional<ItemStack> match = itemAmounts.keySet().stream().filter(is -> is.isSimilar(itemStack)).findFirst();
if(!match.isPresent()){
amount = itemStack.getAmount();
itemAmounts.put(itemStack,amount);
} else {
amount = itemAmounts.get(itemStack.getType()) + itemStack.getAmount();
amount = itemAmounts.get(match.get()) + itemStack.getAmount();
itemAmounts.put(match.get(), amount);
}
itemAmounts.put(itemStack.getType(),amount);
}
return itemAmounts;
}
private static List<ItemStack> condenseInventory(ItemStack[] itemStacks){
HashMap<Material,Integer> itemAmounts = getItemAmounts(itemStacks);
HashMap<ItemStack,Integer> itemAmounts = getItemAmounts(itemStacks);
return condenseInventory(itemAmounts);
}
private static List<ItemStack> condenseInventory(HashMap<Material,Integer> itemAmounts){
private static List<ItemStack> condenseInventory(HashMap<ItemStack,Integer> itemAmounts){
List<ItemStack> condensedItems = new ArrayList<>();
itemAmounts.forEach((material, amount) -> {
int maxStack = material.getMaxStackSize();
itemAmounts.forEach((itemStack, amount) -> {
int maxStack = itemStack.getMaxStackSize();
int amountOfMaxStacks = amount/maxStack;
int remainder = amount % maxStack;
for(int i=0; i<amountOfMaxStacks; i++){
condensedItems.add(new ItemStack(material,maxStack));
condensedItems.add(cloneItem(itemStack,maxStack));
}
if(remainder != 0) condensedItems.add(new ItemStack(material,remainder));
if(remainder != 0) condensedItems.add(cloneItem(itemStack,remainder));
});
return condensedItems;
}
public static Material getMostCommonItem(Inventory inventory){
public static ItemStack getMostCommonItem(Inventory inventory){
return getItemAmounts(inventory.getContents()).entrySet().stream()
.max(Comparator.comparing(Map.Entry::getValue))
.map(Map.Entry::getKey)
.orElse(null);
}
private static ItemStack cloneItem(ItemStack itemStack, int newAmount){
ItemStack item = itemStack.clone();
item.setAmount(newAmount);
return item;
}
}