Added a feature for AutoCrafting items

This commit is contained in:
Brianna O'Keefe 2018-08-28 00:49:55 -04:00
parent a55faf1aee
commit f020975edb
14 changed files with 231 additions and 29 deletions

View File

@ -1,6 +1,7 @@
package com.songoda.epichoppers.api.hopper;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
@ -76,6 +77,20 @@ public interface Hopper {
*/
void setLastPlayer(UUID uuid);
/**
* Get the item being automatically crafted.
*
* @return item being crafted
*/
Material getAutoCrafting();
/**
* Set the Item being automatically crafted.
*
* @param autoCrafting item to craft
*/
void setAutoCrafting(Material autoCrafting);
/**
* Get the teleport trigger is currently enabled.
*

View File

@ -66,6 +66,15 @@ public interface Level {
*/
boolean isTeleport();
/**
* Whether or not hopper crafting is enabled with
* this level.
*
* @return true if crafting is enabled false
* otherwise
*/
boolean isCrafting();
/**
* Get the distance in which a hopper with this
* level will suck items into them.

View File

@ -18,8 +18,9 @@ public interface LevelManager {
* @param blockBreak The tick frequency in which this hopper will break blocks placed directly above it.
* @param filter Whether or not access to the filter is allowed.
* @param teleport Whether or not teleporting through hoppers is allowed.
* @param crafting Whether or not crafting with hoppers is allowed.
*/
void addLevel(int level, int costExperience, int costEconomy, int range, int amount, int suction, int blockBreak, boolean filter, boolean teleport);
void addLevel(int level, int costExperience, int costEconomy, int range, int amount, int suction, int blockBreak, boolean filter, boolean teleport, boolean crafting);
/**
* Get {@link Level} by corresponding integer value.

View File

@ -3,5 +3,5 @@ package com.songoda.epichoppers.api.hopper;
public enum TeleportTrigger {
DISABLED,
WALK_ON,
SNEAK;
SNEAK
}

View File

@ -120,6 +120,8 @@ public class EpicHoppersPlugin extends JavaPlugin implements EpicHoppers {
List<ItemStack> blackList = (ArrayList<ItemStack>) dataFile.getConfig().getList("data.sync." + locationStr + ".blacklist");
List<ItemStack> voidList = (ArrayList<ItemStack>) dataFile.getConfig().getList("data.sync." + locationStr + ".void");
Material autoCrafting = Material.valueOf(dataFile.getConfig().getString("data.sync." + locationStr + ".autoCrafting", "AIR"));
String blackLoc = dataFile.getConfig().getString("data.sync." + locationStr + ".black");
Block black = blackLoc == null ? null : Arconix.pl().getApi().serialize().unserializeLocation(dataFile.getConfig().getString("data.sync." + locationStr + ".black")).getBlock();
@ -130,7 +132,7 @@ public class EpicHoppersPlugin extends JavaPlugin implements EpicHoppers {
filter.setVoidList(voidList);
filter.setEndPoint(black);
EHopper hopper = new EHopper(location, levelManager.getLevel(level), lastPlayer, placedBy, block, filter, teleportTrigger);
EHopper hopper = new EHopper(location, levelManager.getLevel(level), lastPlayer, placedBy, block, filter, teleportTrigger, autoCrafting);
hopperManager.addHopper(location, hopper);
}
@ -216,6 +218,7 @@ public class EpicHoppersPlugin extends JavaPlugin implements EpicHoppers {
dataFile.getConfig().set("data.sync." + locationStr + ".player", hopper.getLastPlayer() == null ? null : hopper.getLastPlayer().toString());
dataFile.getConfig().set("data.sync." + locationStr + ".placedBy", hopper.getPlacedBy() == null ? null : hopper.getPlacedBy().toString());
dataFile.getConfig().set("data.sync." + locationStr + ".teleportTrigger", hopper.getTeleportTrigger().toString());
dataFile.getConfig().set("data.sync." + locationStr + ".autoCrafting", hopper.getAutoCrafting() == Material.AIR ? null : hopper.getAutoCrafting().name());
dataFile.getConfig().set("data.sync." + locationStr + ".whitelist", hopper.getFilter().getWhiteList());
dataFile.getConfig().set("data.sync." + locationStr + ".blacklist", hopper.getFilter().getBlackList());
dataFile.getConfig().set("data.sync." + locationStr + ".void", hopper.getFilter().getVoidList());
@ -250,9 +253,10 @@ public class EpicHoppersPlugin extends JavaPlugin implements EpicHoppers {
int blockBreak = getConfig().getInt("settings.levels." + levelName + ".BlockBreak");
boolean filter = getConfig().getBoolean("settings.levels." + levelName + ".Filter");
boolean teleport = getConfig().getBoolean("settings.levels." + levelName + ".Teleport");
boolean crafting = getConfig().getBoolean("settings.levels." + levelName + ".AutoCrafting");
int costExperiance = getConfig().getInt("settings.levels." + levelName + ".Cost-xp");
int costEconomy = getConfig().getInt("settings.levels." + levelName + ".Cost-eco");
levelManager.addLevel(level, costExperiance, costEconomy, radius, amount, suction, blockBreak, filter, teleport);
levelManager.addLevel(level, costExperiance, costEconomy, radius, amount, suction, blockBreak, filter, teleport, crafting);
}
}
@ -298,6 +302,17 @@ public class EpicHoppersPlugin extends JavaPlugin implements EpicHoppers {
getConfig().addDefault("settings.levels.Level-6.Teleport", true);
getConfig().addDefault("settings.levels.Level-6.Cost-xp", 45);
getConfig().addDefault("settings.levels.Level-6.Cost-eco", 20000);
getConfig().addDefault("settings.levels.Level-7.Range", 70);
getConfig().addDefault("settings.levels.Level-7.Amount", 5);
getConfig().addDefault("settings.levels.Level-7.Suction", 3);
getConfig().addDefault("settings.levels.Level-7.BlockBreak", 2);
getConfig().addDefault("settings.levels.Level-7.Filter", true);
getConfig().addDefault("settings.levels.Level-7.Teleport", true);
getConfig().addDefault("settings.levels.Level-7.AutoCrafting", true);
getConfig().addDefault("settings.levels.Level-7.Cost-xp", 50);
getConfig().addDefault("settings.levels.Level-7.Cost-eco", 30000);
}
getConfig().options().copyDefaults(true);

View File

@ -11,10 +11,7 @@ import org.bukkit.block.Hopper;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Item;
import org.bukkit.inventory.FurnaceInventory;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.*;
import org.bukkit.metadata.FixedMetadataValue;
import java.util.*;
@ -24,6 +21,7 @@ import java.util.*;
*/
public class HopHandler {
public Map<Block, Integer> blockTick = new HashMap<>();
private EpicHoppersPlugin instance;
public HopHandler(EpicHoppersPlugin instance) {
@ -57,8 +55,6 @@ public class HopHandler {
}
}
public Map<Block, Integer> blockTick = new HashMap<>();
private void hopperRunner() {
try {
Set<Entity> metaItems = new HashSet<>();
@ -87,6 +83,26 @@ public class HopHandler {
org.bukkit.block.Hopper hopperBlock = (org.bukkit.block.Hopper) (block != null ? block.getState() : null);
ItemStack[] is = hopperBlock.getInventory().getContents();
if (hopper.getAutoCrafting() != null && canMove(hopperBlock.getInventory(), new ItemStack(hopper.getAutoCrafting()))) {
main:
for (Recipe recipe : Bukkit.getServer().getRecipesFor(new ItemStack(hopper.getAutoCrafting()))) {
if (!(recipe instanceof ShapedRecipe)) continue;
Map<Character, ItemStack> ingredientMap = ((ShapedRecipe) recipe).getIngredientMap();
if (hopperBlock.getInventory().getSize() == 0) continue;
List<ItemStack> needed = stackItems(new ArrayList<>(ingredientMap.values()));
for (ItemStack item : needed) {
if (!hopperBlock.getInventory().contains(item.getType(), item.getAmount())) continue main;
}
for (ItemStack item : needed) {
hopperBlock.getInventory().removeItem(item);
}
hopperBlock.getInventory().addItem(new ItemStack(hopper.getAutoCrafting()));
}
}
if (hopper.getLevel().getBlockBreak() != 0) {
int amt = hopper.getLevel().getBlockBreak();
if (!blockTick.containsKey(block)) {
@ -171,12 +187,22 @@ public class HopHandler {
int amt = hopper.getLevel().getAmount() * (boostData == null ? 1 : boostData.getMultiplier());
ItemStack[] is = hopperBlock.getInventory().getContents();
List<ItemStack> whiteList = hopper.getFilter().getWhiteList();
List<ItemStack> blackList = hopper.getFilter().getBlackList();
List<Material> materials = new ArrayList<>();
if (hopper.getAutoCrafting() != null) {
for (Recipe recipe : Bukkit.getServer().getRecipesFor(new ItemStack(hopper.getAutoCrafting()))) {
if (recipe instanceof ShapedRecipe) {
for (ItemStack itemStack : ((ShapedRecipe) recipe).getIngredientMap().values()) {
if (itemStack == null) continue;
materials.add(itemStack.getType());
}
}
}
}
int num = 0;
while (num != 5) {
ItemStack it = null;
@ -184,6 +210,13 @@ public class HopHandler {
it = is[num].clone();
it.setAmount(1);
}
if (is[num] != null
&& materials.contains(is[num].getType())) {
num++;
continue;
}
if (is[num] != null
&& !whiteList.isEmpty()
&& !whiteList.contains(it)) {
@ -206,6 +239,23 @@ public class HopHandler {
}
}
private List<ItemStack> stackItems(List<ItemStack> items) {
Map<Material, Integer> materials = new HashMap<>();
for (ItemStack itemStack : items) {
if (itemStack == null) continue;
if (materials.containsKey(itemStack.getType())) {
materials.put(itemStack.getType(), materials.get(itemStack.getType()) + itemStack.getAmount());
continue;
}
materials.put(itemStack.getType(), itemStack.getAmount());
}
List<ItemStack> stacked = new ArrayList<>();
for (Map.Entry<Material, Integer> entry : materials.entrySet()) {
stacked.add(new ItemStack(entry.getKey(), entry.getValue()));
}
return stacked;
}
private void doBlacklist(Hopper hopperBlock, com.songoda.epichoppers.api.hopper.Hopper hopper, ItemStack item, ItemStack[] isS, int amt, int place) {
try {
Location loc = hopperBlock.getLocation();
@ -318,6 +368,21 @@ public class HopHandler {
return 0;
}
private boolean canMove(Inventory inventory, ItemStack item) {
try {
if (inventory.firstEmpty() != -1) return true;
for (ItemStack stack : inventory.getContents()) {
if (stack.isSimilar(item) && stack.getAmount() < stack.getMaxStackSize()) {
return true;
}
}
} catch (Exception e) {
Debugger.runReport(e);
}
return false;
}
public boolean canHop(Inventory i, ItemStack item, int hop) {
try {
if (i.firstEmpty() != -1) {

View File

@ -38,9 +38,10 @@ public class EHopper implements Hopper {
private Block syncedBlock;
private Filter filter;
private TeleportTrigger teleportTrigger;
private Material autoCrafting;
public EHopper(Location location, com.songoda.epichoppers.api.hopper.Level level, UUID lastPlayer, UUID placedBy, Block syncedBlock, Filter filter, TeleportTrigger teleportTrigger) {
public EHopper(Location location, com.songoda.epichoppers.api.hopper.Level level, UUID lastPlayer, UUID placedBy, Block syncedBlock, Filter filter, TeleportTrigger teleportTrigger, Material autoCrafting) {
this.location = location;
this.level = level;
this.syncedBlock = syncedBlock;
@ -48,10 +49,11 @@ public class EHopper implements Hopper {
this.lastPlayer = lastPlayer;
this.placedBy = placedBy;
this.teleportTrigger = teleportTrigger;
this.autoCrafting = autoCrafting;
}
public EHopper(Block block, com.songoda.epichoppers.api.hopper.Level level, UUID lastPlayer, UUID placedBy, Block syncedBlock, Filter filter, TeleportTrigger teleportTrigger) {
this(block.getLocation(), level, lastPlayer, placedBy, syncedBlock, filter, teleportTrigger);
public EHopper(Block block, com.songoda.epichoppers.api.hopper.Level level, UUID lastPlayer, UUID placedBy, Block syncedBlock, Filter filter, TeleportTrigger teleportTrigger, Material autoCrafting) {
this(block.getLocation(), level, lastPlayer, placedBy, syncedBlock, filter, teleportTrigger, autoCrafting);
}
public void overview(Player player) {
@ -91,6 +93,17 @@ public class EHopper implements Hopper {
filtermeta.setLore(lorefilter);
filter.setItemMeta(filtermeta);
ItemStack crafting = new ItemStack(Material.CRAFTING_TABLE, 1);
ItemMeta craftingmeta = crafting.getItemMeta();
craftingmeta.setDisplayName(instance.getLocale().getMessage("interface.hopper.craftingtitle"));
ArrayList<String> lorecrafting = new ArrayList<>();
parts = instance.getLocale().getMessage("interface.hopper.craftinglore").split("\\|");
for (String line : parts) {
lorecrafting.add(Arconix.pl().getApi().format().formatText(line));
}
craftingmeta.setLore(lorecrafting);
crafting.setItemMeta(craftingmeta);
ItemStack item = new ItemStack(Material.HOPPER, 1);
ItemMeta itemmeta = item.getItemMeta();
@ -164,12 +177,19 @@ public class EHopper implements Hopper {
i.setItem(5, filter);
}
boolean canCraft = level.isCrafting() || player.hasPermission("EpicHoppers.Crafting");
if (!canCraft)
i.setItem(22, hook);
else if (canFilter) {
i.setItem(23, hook);
i.setItem(21, crafting);
}
if (instance.getConfig().getBoolean("Main.Upgrade With XP") && player.hasPermission("EpicHoppers.Upgrade.XP")) {
i.setItem(11, itemXP);
}
i.setItem(13, item);
i.setItem(22, hook);
if (instance.getConfig().getBoolean("Main.Upgrade With Economy") && player.hasPermission("EpicHoppers.Upgrade.ECO")) {
i.setItem(15, itemECO);
@ -200,6 +220,46 @@ public class EHopper implements Hopper {
}
}
public void crafting(Player player) {
try {
EpicHoppersPlugin instance = EpicHoppersPlugin.getInstance();
instance.getPlayerDataManager().getPlayerData(player).setLastHopper(this);
Inventory i = Bukkit.createInventory(null, 27, Arconix.pl().getApi().format().formatText(Methods.formatName(level.getLevel(), false) + " &8-&f Crafting"));
int nu = 0;
while (nu != 27) {
i.setItem(nu, Methods.getGlass());
nu++;
}
i.setItem(0, Methods.getBackgroundGlass(true));
i.setItem(1, Methods.getBackgroundGlass(true));
i.setItem(2, Methods.getBackgroundGlass(false));
i.setItem(6, Methods.getBackgroundGlass(false));
i.setItem(7, Methods.getBackgroundGlass(true));
i.setItem(8, Methods.getBackgroundGlass(true));
i.setItem(9, Methods.getBackgroundGlass(true));
i.setItem(10, Methods.getBackgroundGlass(false));
i.setItem(16, Methods.getBackgroundGlass(false));
i.setItem(17, Methods.getBackgroundGlass(true));
i.setItem(18, Methods.getBackgroundGlass(true));
i.setItem(19, Methods.getBackgroundGlass(true));
i.setItem(20, Methods.getBackgroundGlass(false));
i.setItem(24, Methods.getBackgroundGlass(false));
i.setItem(25, Methods.getBackgroundGlass(true));
i.setItem(26, Methods.getBackgroundGlass(true));
i.setItem(13, new ItemStack(autoCrafting == null ? Material.AIR : autoCrafting));
player.openInventory(i);
instance.getPlayerDataManager().getPlayerData(player).setInMenu(MenuType.CRAFTING);
lastPlayer = player.getUniqueId();
} catch (Exception e) {
Debugger.runReport(e);
}
}
public void filter(Player player) {
try {
EpicHoppersPlugin instance = EpicHoppersPlugin.getInstance();
@ -520,6 +580,16 @@ public class EHopper implements Hopper {
lastPlayer = uuid;
}
@Override
public Material getAutoCrafting() {
return autoCrafting;
}
@Override
public void setAutoCrafting(Material autoCrafting) {
this.autoCrafting = autoCrafting;
}
@Override
public TeleportTrigger getTeleportTrigger() {
return teleportTrigger;

View File

@ -29,7 +29,7 @@ public class EHopperManager implements HopperManager {
@Override
public Hopper getHopper(Location location) {
if (!registeredHoppers.containsKey(roundLocation(location))) {
addHopper(location, new EHopper(location, EpicHoppersPlugin.getInstance().getLevelManager().getLowestLevel(), null, null, null, new EFilter(), TeleportTrigger.DISABLED));
addHopper(location, new EHopper(location, EpicHoppersPlugin.getInstance().getLevelManager().getLowestLevel(), null, null, null, new EFilter(), TeleportTrigger.DISABLED, null));
}
return registeredHoppers.get(roundLocation(location));
}

View File

@ -10,11 +10,11 @@ public class ELevel implements Level {
private int level, costExperience, costEconomy, range, amount, blockBreak, suction;
private boolean filter, teleport;
private boolean filter, teleport, crafting;
private List<String> description = new ArrayList<>();
public ELevel(int level, int costExperience, int costEconomy, int range, int amount, int suction, int blockBreak, boolean filter, boolean teleport) {
public ELevel(int level, int costExperience, int costEconomy, int range, int amount, int suction, int blockBreak, boolean filter, boolean teleport, boolean crafting) {
this.level = level;
this.costExperience = costExperience;
this.costEconomy = costEconomy;
@ -24,6 +24,7 @@ public class ELevel implements Level {
this.suction = suction;
this.filter = filter;
this.teleport = teleport;
this.crafting = crafting;
EpicHoppersPlugin instance = EpicHoppersPlugin.getInstance();
@ -32,7 +33,8 @@ public class ELevel implements Level {
if (suction != 0) description.add(instance.getLocale().getMessage("interface.hopper.suction", suction));
if (blockBreak != 0) description.add(instance.getLocale().getMessage("interface.hopper.blockbreak", blockBreak));
if (filter) description.add(instance.getLocale().getMessage("interface.hopper.filter", true));
if (teleport) description.add(instance.getLocale().getMessage("interface.hopper.filter", true));
if (teleport) description.add(instance.getLocale().getMessage("interface.hopper.teleport", true));
if (crafting) description.add(instance.getLocale().getMessage("interface.hopper.crafting", true));
}
@Override
@ -70,6 +72,11 @@ public class ELevel implements Level {
return teleport;
}
@Override
public boolean isCrafting() {
return crafting;
}
@Override
public int getSuction() {
return suction;

View File

@ -13,8 +13,8 @@ public class ELevelManager implements LevelManager {
private final NavigableMap<Integer, ELevel> registeredLevels = new TreeMap<>();
@Override
public void addLevel(int level, int costExperience, int costEconomy, int range, int amount, int suction, int blockBreak, boolean filter, boolean teleport) {
registeredLevels.put(level, new ELevel(level, costExperience, costEconomy, range, amount, suction, blockBreak, filter, teleport));
public void addLevel(int level, int costExperience, int costEconomy, int range, int amount, int suction, int blockBreak, boolean filter, boolean teleport, boolean crafting) {
registeredLevels.put(level, new ELevel(level, costExperience, costEconomy, range, amount, suction, blockBreak, filter, teleport, crafting));
}
@Override

View File

@ -56,7 +56,7 @@ public class BlockListeners implements Listener {
ItemStack item = e.getItemInHand().clone();
instance.getHopperManager().addHopper(e.getBlock().getLocation(), new EHopper(e.getBlock(), instance.getLevelFromItem(item), e.getPlayer().getUniqueId(), e.getPlayer().getUniqueId(),null, new EFilter(), TeleportTrigger.DISABLED));
instance.getHopperManager().addHopper(e.getBlock().getLocation(), new EHopper(e.getBlock(), instance.getLevelFromItem(item), e.getPlayer().getUniqueId(), e.getPlayer().getUniqueId(),null, new EFilter(), TeleportTrigger.DISABLED, null));
} catch (Exception ee) {
Debugger.runReport(ee);

View File

@ -32,7 +32,6 @@ public class InventoryListeners implements Listener {
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
try {
Inventory inv = event.getInventory();
Player player = (Player) event.getWhoClicked();
if (inv == null || event.getCurrentItem() == null) return;
@ -71,6 +70,14 @@ public class InventoryListeners implements Listener {
PlayerData playerData = instance.getPlayerDataManager().getPlayerData(player);
if (playerData.getInMenu() == MenuType.CRAFTING) {
if (event.getSlot() == 13) {
return;
}
event.setCancelled(true);
return;
}
if (playerData.getInMenu() != MenuType.OVERVIEW) return;
event.setCancelled(true);
@ -94,8 +101,6 @@ public class InventoryListeners implements Listener {
return;
}
player.closeInventory();
} else if (event.getCurrentItem().getItemMeta().hasDisplayName() && event.getCurrentItem().getItemMeta().getDisplayName().equals(instance.getLocale().getMessage("interface.hopper.filtertitle")) && (hopper.getLevel().isFilter() || player.hasPermission("EpicHoppers.Filter"))) {
if (!event.getCurrentItem().getItemMeta().getDisplayName().equals("§l")) {
((EHopper)hopper).filter(player);
@ -110,7 +115,9 @@ public class InventoryListeners implements Listener {
((EHopper)hopper).upgrade("ECO", player);
player.closeInventory();
}
} else if (event.getSlot() == 22) {
} else if (event.getCurrentItem().getItemMeta().getDisplayName().equals(instance.getLocale().getMessage("interface.hopper.craftingtitle"))) {
((EHopper)hopper).crafting(player);
} else if (event.getCurrentItem().getItemMeta().getDisplayName().equals(instance.getLocale().getMessage("interface.hopper.synchopper"))) {
if (event.isRightClick()) {
player.sendMessage(instance.references.getPrefix() + instance.getLocale().getMessage("event.hopper.desync"));
hopper.setSyncedBlock(null);
@ -135,6 +142,7 @@ public class InventoryListeners implements Listener {
}
}
private boolean doFilter(InventoryClickEvent e) {
Player player = (Player) e.getWhoClicked();
PlayerData playerData = instance.getPlayerDataManager().getPlayerData(player);
@ -212,8 +220,14 @@ public class InventoryListeners implements Listener {
try {
Player player = (Player)event.getPlayer();
PlayerData playerData = instance.getPlayerDataManager().getPlayerData(player);
if (playerData.getInMenu() == MenuType.CRAFTING) {
Hopper hopper = instance.getHopperManager().getHopperFromPlayer(player);
ItemStack item = event.getInventory().getItem(13);
hopper.setAutoCrafting(item == null ? Material.AIR : item.getType());
}
if (playerData.getInMenu() != MenuType.NOT_IN) {
Hopper hopper = instance.getHopperManager().getHopperFromPlayer(player);
if (hopper != null)
hopper.setLastPlayer(null);
}
if (playerData.getInMenu() == MenuType.FILTER) {

View File

@ -4,6 +4,7 @@ public enum MenuType {
NOT_IN,
OVERVIEW,
FILTER
FILTER,
CRAFTING
}

View File

@ -16,6 +16,9 @@ interface.hopper.currentlevel = "&6Hopper Level &7%level%"
interface.hopper.nextlevel = "&6Next Level &7%level%"
interface.hopper.range = "&7Range: &6%range%"
interface.hopper.amount = "&7Amount: &6%amount%"
interface.hopper.teleport = "&7Teleport: &6%enabled%"
interface.hopper.filter = "&7Filter: &6%enabled%"
interface.hopper.crafting = "&7AutoCrafting: &6%enabled%"
interface.hopper.suction = "&7Suction: &6%suction%"
interface.hopper.blockbreak = "&7Block Break: &6Every %ticks% ticks"
interface.hopper.alreadymaxed = "&7This hopper is already maxed out!"
@ -24,6 +27,8 @@ interface.hopper.perltitle = "&6Click to Teleport"
interface.hopper.perllore2 = "|&7Left-Click to teleport to|&7the end of the chain.||&7Right-Click to switch the|&7teleport trigger mode.|&7Currently set to: &a%type%&7."
interface.hopper.filtertitle = "&cClick to Filter"
interface.hopper.filterlore = "|&7This allows you to choose|&7which items go where."
interface.hopper.craftingtitle = "&cClick to setup AutoCrafting"
interface.hopper.craftinglore = "|&7This allows you to choose|&7which item this hopper|&7will automaticly craft."
interface.hopper.synchopper = "&6Click to Sync This hopper"
interface.hopper.rejectsync = "&6Click to Sync Rejected Items"
interface.filter.infotitle = "&aFilter Guide"