Merge branch 'development'

This commit is contained in:
Brianna 2019-10-03 10:52:53 -04:00
commit 33150134e6
15 changed files with 322 additions and 130 deletions

View File

@ -4,7 +4,7 @@ stages:
variables:
name: "EpicHoppers"
path: "/builds/$CI_PROJECT_PATH"
version: "4.2.6"
version: "4.2.10"
build:
stage: build

12
pom.xml
View File

@ -68,8 +68,8 @@
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.14.4-R0.1-SNAPSHOT</version>
<artifactId>spigot</artifactId>
<version>1.14.1</version>
</dependency>
<dependency>
<groupId>com.songoda</groupId>
@ -106,14 +106,14 @@
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>fabledskyblock</artifactId>
<version>78.5</version>
<artifactId>abledskyblock</artifactId>
<version>79.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.songoda</groupId>
<artifactId>epicfarming</artifactId>
<version>2.2.1</version>
<artifactId>EpicFarming</artifactId>
<version>2.3.1</version>
<scope>provided</scope>
</dependency>
<dependency>

View File

@ -19,51 +19,36 @@ public class CommandBoost extends AbstractCommand {
@Override
protected ReturnType runCommand(EpicHoppers instance, CommandSender sender, String... args) {
if (args.length < 3) {
instance.getLocale().newMessage("&7Syntax error...").sendPrefixedMessage(sender);
return ReturnType.SYNTAX_ERROR;
}
if (Bukkit.getPlayer(args[1]) == null) {
instance.getLocale().newMessage("&cThat player does not exist...").sendPrefixedMessage(sender);
return ReturnType.FAILURE;
} else if (!Methods.isInt(args[2])) {
if (!Methods.isInt(args[2])) {
instance.getLocale().newMessage("&6" + args[2] + " &7is not a number...").sendPrefixedMessage(sender);
return ReturnType.FAILURE;
} else {
Calendar c = Calendar.getInstance();
Date currentDate = new Date();
c.setTime(currentDate);
String time = "&7.";
if (args.length > 3) {
if (args[3].contains("m:")) {
String[] arr2 = (args[3]).split(":");
c.add(Calendar.MINUTE, Integer.parseInt(arr2[1]));
time = " &7for &6" + arr2[1] + " minutes&7.";
} else if (args[3].contains("h:")) {
String[] arr2 = (args[3]).split(":");
c.add(Calendar.HOUR, Integer.parseInt(arr2[1]));
time = " &7for &6" + arr2[1] + " hours&7.";
} else if (args[3].contains("d:")) {
String[] arr2 = (args[3]).split(":");
c.add(Calendar.HOUR, Integer.parseInt(arr2[1]) * 24);
time = " &7for &6" + arr2[1] + " days&7.";
} else if (args[3].contains("y:")) {
String[] arr2 = (args[3]).split(":");
c.add(Calendar.YEAR, Integer.parseInt(arr2[1]));
time = " &7for &6" + arr2[1] + " years&7.";
} else {
instance.getLocale().newMessage("&7" + args[3] + " &7is invalid.").sendPrefixedMessage(sender);
return ReturnType.SUCCESS;
}
} else {
c.add(Calendar.YEAR, 10);
}
BoostData boostData = new BoostData(Integer.parseInt(args[2]), c.getTime().getTime(), Bukkit.getPlayer(args[1]).getUniqueId());
instance.getBoostManager().addBoostToPlayer(boostData);
instance.getLocale().newMessage("&7Successfully boosted &6" + Bukkit.getPlayer(args[1]).getName() + "'s &7hoppers transfer rates by &6" + args[2] + "x" + time).sendPrefixedMessage(sender);
return ReturnType.SYNTAX_ERROR;
}
return ReturnType.FAILURE;
long duration = 0L;
if (args.length > 3) {
for (int i = 1; i < args.length; i++) {
String line = args[i];
long time = Methods.parseTime(line);
duration += time;
}
}
Player player = Bukkit.getPlayer(args[1]);
if (player == null) {
instance.getLocale().newMessage("&cThat player does not exist or is not online...").sendPrefixedMessage(sender);
return ReturnType.FAILURE;
}
BoostData boostData = new BoostData(Integer.parseInt(args[2]), duration == 0L ? Long.MAX_VALUE : System.currentTimeMillis() + duration, player.getUniqueId());
instance.getBoostManager().addBoostToPlayer(boostData);
instance.getLocale().newMessage("&7Successfully boosted &6" + Bukkit.getPlayer(args[1]).getName()
+ "'s &7hopper transfer rates by &6" + args[2] + "x" + (duration == 0L ? "" : (" for " + Methods.makeReadable(duration))) + "&7.").sendPrefixedMessage(sender);
return ReturnType.SUCCESS;
}
@Override
@ -77,7 +62,7 @@ public class CommandBoost extends AbstractCommand {
} else if (args.length == 3) {
return Arrays.asList("1", "2", "3", "4", "5");
} else if (args.length == 4) {
return Arrays.asList("m:", "h:", "d:", "y:");
return Arrays.asList("1m", "1h", "1d");
}
return null;
}
@ -89,7 +74,7 @@ public class CommandBoost extends AbstractCommand {
@Override
public String getSyntax() {
return "/eh boost <player> <multiplier> [m:minute, h:hour, d:day, y:year]";
return "/eh boost <player> <amount> [duration]";
}
@Override

View File

@ -1,12 +1,15 @@
package com.songoda.epichoppers.enchantment;
import com.songoda.epichoppers.utils.Methods;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.List;
/**
* Created by songoda on 3/22/2017.
@ -15,10 +18,17 @@ public class Enchantment {
public ItemStack createSyncTouch(ItemStack item, Block block) {
ItemMeta itemmeta = item.getItemMeta();
ArrayList<String> lore = new ArrayList<>();
List<String> lore = itemmeta.hasLore() ? itemmeta.getLore() : new ArrayList<>();
for (String str : lore) {
if (!str.contains("Sync Touch")) continue;
lore.remove(str);
break;
}
if (block != null) {
lore.add(Methods.formatText("&aSync Touch"));
lore.add(Methods.convertToInvisibleString(Methods.serializeLocation(block)));
lore.add(Methods.convertToInvisibleString(Methods.serializeLocation(block) + "~")
+ Methods.formatText("&aSync Touch"));
} else {
lore.add(Methods.formatText("&7Sync Touch"));
}

View File

@ -126,7 +126,7 @@ public class Hopper {
EpicHoppers instance = EpicHoppers.getInstance();
Bukkit.getScheduler().scheduleSyncDelayedTask(instance, () -> {
PlayerData playerData = instance.getPlayerDataManager().getPlayerData(player);
if (playerData.getSyncType() != null) {
if (playerData.getSyncType() != null && playerData.getLastHopper() == this) {
instance.getLocale().getMessage("event.hopper.synctimeout").sendPrefixedMessage(player);
playerData.setSyncType(null);
}

View File

@ -11,16 +11,22 @@ import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class Module {
private static final Map<String, ConfigWrapper> configs = new HashMap<>();
protected final EpicHoppers plugin;
private final ConfigWrapper config;
public Module(EpicHoppers plugin) {
this.plugin = plugin;
this.config = new ConfigWrapper(plugin, File.separator + "modules", getName() + ".yml");
if (!configs.containsKey(getName()))
configs.put(getName(), new ConfigWrapper(plugin, File.separator + "modules", getName() + ".yml"));
this.config = configs.get(getName());
}
public abstract String getName();

View File

@ -77,7 +77,7 @@ public class ModuleBlockBreak extends Module {
Block above = hopper.getLocation().getBlock().getRelative(0, 1, 0);
// Don't break farm items from EpicFarming
if (plugin.isEpicFarming() && com.songoda.epicfarming.EpicFarmingPlugin.getInstance().getFarmManager().getFarm(above) != null)
if (plugin.isEpicFarming() && com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager().getFarm(above) != null)
return;
// don't break blacklisted blocks, fluids, or containers

View File

@ -6,8 +6,6 @@ import com.songoda.epichoppers.hopper.Hopper;
import com.songoda.epichoppers.utils.Methods;
import com.songoda.epichoppers.utils.ServerVersion;
import com.songoda.epichoppers.utils.StorageContainerCache;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -18,12 +16,11 @@ import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
public class ModuleSuction extends Module {

View File

@ -6,6 +6,7 @@ import com.songoda.epichoppers.hopper.HopperBuilder;
import com.songoda.epichoppers.hopper.levels.Level;
import com.songoda.epichoppers.utils.Methods;
import com.songoda.epichoppers.utils.ServerVersion;
import org.bukkit.ChatColor;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
@ -23,6 +24,10 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.permissions.PermissionAttachmentInfo;
import java.util.ArrayList;
import java.util.Map;
import java.util.Random;
/**
* Created by songoda on 3/14/2017.
@ -30,9 +35,11 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
public class BlockListeners implements Listener {
private final EpicHoppers instance;
private final Random random;
public BlockListeners(EpicHoppers instance) {
this.instance = instance;
this.random = new Random();
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
@ -68,7 +75,9 @@ public class BlockListeners implements Listener {
int limit = -1;
for (PermissionAttachmentInfo permissionAttachmentInfo : player.getEffectivePermissions()) {
if (!permissionAttachmentInfo.getPermission().toLowerCase().startsWith("epichoppers.limit")) continue;
limit = Integer.parseInt(permissionAttachmentInfo.getPermission().split("\\.")[2]);
int num = Integer.parseInt(permissionAttachmentInfo.getPermission().split("\\.")[2]);
if (num > limit)
limit = num;
}
if (limit == -1) limit = instance.getConfig().getInt("Main.Max Hoppers Per Chunk");
return limit;
@ -130,9 +139,17 @@ public class BlockListeners implements Listener {
ItemStack tool = event.getPlayer().getInventory().getItemInHand();
ItemMeta meta = tool.getItemMeta();
if (tool.getItemMeta().getLore().size() != 2) return;
Location location = null;
Location location = Methods.unserializeLocation(meta.getLore().get(1).replaceAll("§", ""));
for (String lore : meta.getLore()) {
if (!lore.contains(Methods.formatText("&aSync Touch"))) continue;
String[] loreSplit = lore.split("~");
location = Methods.unserializeLocation(loreSplit[0].replace(ChatColor.COLOR_CHAR + "", "")
.replace("~", ""));
break;
}
if (location == null) return;
if (location.getBlock().getType() != Material.CHEST) return;
@ -147,9 +164,21 @@ public class BlockListeners implements Listener {
if (event.getPlayer().getInventory().getItemInHand().getItemMeta().hasEnchant(Enchantment.SILK_TOUCH)) {
ih.getInventory().addItem(new ItemStack(event.getBlock().getType(), 1, event.getBlock().getData()));
} else {
for (ItemStack is : event.getBlock().getDrops())
ih.getInventory().addItem(is);
if (event.getPlayer().getInventory().getItemInHand().getItemMeta().hasEnchant(Enchantment.LOOT_BONUS_BLOCKS)) {
int level = event.getPlayer().getInventory().getItemInHand().getItemMeta().getEnchantLevel(Enchantment.LOOT_BONUS_BLOCKS);
int dropAmount = calculateFortuneDrops(event.getBlock().getType(), level, random);
for (int i = 0; i < dropAmount; i++) {
for (ItemStack is : event.getBlock().getDrops()) ih.getInventory().addItem(is);
}
} else {
for (ItemStack is : event.getBlock().getDrops()) {
Map<Integer, ItemStack> notDropped = ih.getInventory().addItem(is);
if (!notDropped.isEmpty())
location.getWorld().dropItemNaturally(event.getBlock().getLocation(), new ArrayList<>(notDropped.values()).get(0));
}
}
}
if (instance.isServerVersionAtLeast(ServerVersion.V1_12)) {
event.setDropItems(false);
return;
@ -165,4 +194,15 @@ public class BlockListeners implements Listener {
event.getBlock().setType(Material.AIR);
}
private int calculateFortuneDrops(Material material, int level, Random random) {
if (level <= 0) return 1;
int drops = random.nextInt(level + 2) - 1;
if (drops < 0) drops = 0;
return applyLapisDrops(material, random) * (drops + 1);
}
private int applyLapisDrops(Material material, Random random) {
return material == Material.LAPIS_ORE ? 4 + random.nextInt(5) : 1;
}
}

View File

@ -17,6 +17,7 @@ import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
@ -52,7 +53,9 @@ public class EntityListeners implements Listener {
if (location.getBlock().getType() != Material.CHEST) return;
InventoryHolder ih = (InventoryHolder) location.getBlock().getState();
for (ItemStack is : event.getDrops()) {
ih.getInventory().addItem(is);
Map<Integer, ItemStack> notDropped = ih.getInventory().addItem(is);
if (!notDropped.isEmpty())
location.getWorld().dropItemNaturally(event.getEntity().getLocation(), new ArrayList<>(notDropped.values()).get(0));
}
event.getDrops().clear();
}

View File

@ -61,7 +61,15 @@ public class InteractListeners implements Listener {
if (e.getClickedBlock().getType() == Material.CHEST && Methods.isSync(player)) {
ItemStack item = e.getPlayer().getInventory().getItemInHand();
if (item.getItemMeta().getLore().size() == 2) {
boolean isLinked = false;
for (String lore : item.getItemMeta().getLore()) {
if (!lore.contains(Methods.formatText("&aSync Touch"))) continue;
isLinked = true;
break;
}
if (isLinked) {
instance.getLocale().getMessage("event.hopper.desyncchest")
.processPlaceholder("name", item.getType().toString()).sendPrefixedMessage(player);
instance.enchantmentHandler.createSyncTouch(item, null);

View File

@ -9,9 +9,6 @@ import com.songoda.epichoppers.utils.HopperDirection;
import com.songoda.epichoppers.utils.Methods;
import com.songoda.epichoppers.utils.StorageContainerCache;
import com.songoda.epichoppers.utils.settings.Setting;
import me.goodandevil.skyblock.SkyBlock;
import me.goodandevil.skyblock.stackable.Stackable;
import me.goodandevil.skyblock.stackable.StackableManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -25,13 +22,10 @@ import org.bukkit.entity.minecart.StorageMinecart;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@ -47,12 +41,20 @@ public class HopTask extends BukkitRunnable {
private final int hopTicks;
private final boolean hasFabledSkyBlock;
private boolean legacyFabledSkyblock;
private final Plugin fabledSkyblockPlugin;
public HopTask(EpicHoppers plug) {
plugin = plug;
this.hopTicks = Math.max(1, Setting.HOP_TICKS.getInt() / 2); // Purposeful integer division. Don't go below 1.
this.runTaskTimer(plugin, 0, 2);
this.hasFabledSkyBlock = Bukkit.getPluginManager().isPluginEnabled("FabledSkyBlock");
if ((this.hasFabledSkyBlock = (fabledSkyblockPlugin = Bukkit.getPluginManager().getPlugin("FabledSkyBlock")) != null)) {
try {
Class.forName("me.goodandevil.skyblock.SkyBlock");
legacyFabledSkyblock = true;
} catch (ClassNotFoundException ex) {
}
}
}
@Override
@ -128,11 +130,11 @@ public class HopTask extends BukkitRunnable {
// Can we check this item?
if ( // Ignore this one if the slot is empty
item == null
// Don't try to move items that we've added this round
|| (hopperCache.cacheChanged[i] && item.getAmount() - hopperCache.cacheAdded[i] < maxToMove)
// skip if blocked or voidlisted
|| blockedMaterials.contains(item.getType())
|| hopper.getFilter().getVoidList().stream().anyMatch(itemStack -> Methods.isSimilarMaterial(itemStack, item)))
// Don't try to move items that we've added this round
|| (hopperCache.cacheChanged[i] && item.getAmount() - hopperCache.cacheAdded[i] < maxToMove)
// skip if blocked or voidlisted
|| blockedMaterials.contains(item.getType())
|| hopper.getFilter().getVoidList().stream().anyMatch(itemStack -> Methods.isSimilarMaterial(itemStack, item)))
continue;
doProcess = true;
@ -143,23 +145,53 @@ public class HopTask extends BukkitRunnable {
// Support for FabledSkyBlock stackables.
if (this.hasFabledSkyBlock) {
StackableManager stackableManager = SkyBlock.getInstance().getStackableManager();
if (stackableManager != null && stackableManager.isStacked(pointingLocation)) {
Stackable stackable = stackableManager.getStack(pointingLocation, pointingLocation.getBlock().getType());
if (legacyFabledSkyblock) {
Object stackableManager = fabledSkyblockPlugin.getClass().getMethod("getStackableManager").invoke(fabledSkyblockPlugin);
boolean isStacked = stackableManager != null && (boolean) stackableManager.getClass().getMethod("isStacked", Location.class).invoke(stackableManager, pointingLocation);
if (isStacked) {
Material mat = pointingLocation.getBlock().getType();
Object stackable = stackableManager.getClass().getMethod("getStack", Location.class, Material.class).invoke(stackableManager, pointingLocation, mat);
for (int i = 0; i < 5; i++) {
final ItemStack item = hopperCache.cachedInventory[i];
if (item == null) continue;
if (item.getType() == stackable.getMaterial()) {
stackable.addOne();
if (item.getAmount() == 1) {
hopperCache.removeItem(i);
} else {
item.setAmount(item.getAmount() - 1);
hopperCache.dirty = hopperCache.cacheChanged[i] = true;
for (int i = 0; i < 5; i++) {
final ItemStack item = hopperCache.cachedInventory[i];
if (item == null) {
continue;
}
if (item.getType() == mat) {
stackable.getClass().getMethod("addOne").invoke(stackable);
if (item.getAmount() == 1) {
hopperCache.removeItem(i);
} else {
item.setAmount(item.getAmount() - 1);
hopperCache.dirty = hopperCache.cacheChanged[i] = true;
}
break;
}
}
}
} else {
com.songoda.skyblock.stackable.StackableManager stackableManager = ((com.songoda.skyblock.SkyBlock) fabledSkyblockPlugin).getStackableManager();
if (stackableManager != null && stackableManager.isStacked(pointingLocation)) {
Material mat = pointingLocation.getBlock().getType();
com.songoda.skyblock.stackable.Stackable stackable = stackableManager.getStack(pointingLocation, mat);
for (int i = 0; i < 5; i++) {
final ItemStack item = hopperCache.cachedInventory[i];
if (item == null) {
continue;
}
if (item.getType() == mat) {
stackable.addOne();
if (item.getAmount() == 1) {
hopperCache.removeItem(i);
} else {
item.setAmount(item.getAmount() - 1);
hopperCache.dirty = hopperCache.cacheChanged[i] = true;
}
break;
}
break;
}
}
}
@ -233,9 +265,9 @@ public class HopTask extends BukkitRunnable {
contents = aboveCache.cachedInventory;
aboveInvHolder = null;
} else if (isFarmItem) {
aboveInvHolder = this.getEpicFarmingItemWrapped(above);
pullableSlots = IntStream.rangeClosed(27, 53).toArray();
contents = aboveInvHolder.getInventory().getContents();
aboveInvHolder = null;
contents = getFarmContents(above);
pullableSlots = IntStream.rangeClosed(0, contents.length - 1).toArray();
} else {
if ((aboveInvHolder = this.getRandomInventoryHolderFromEntities(nearbyEntities)) == null)
return;
@ -257,7 +289,7 @@ public class HopTask extends BukkitRunnable {
final ItemStack toMove = contents[i];
// If item is invalid, try the next slot.
if (toMove == null)
if (toMove == null || toMove.getAmount() == 0)
continue;
// if we're not moving the item that we're trying to craft, we need to verify that we're not trying to fill the last slot
@ -267,12 +299,12 @@ public class HopTask extends BukkitRunnable {
// respect whitelist/blacklist filters
if (toHopper.getFilter().getEndPoint() == null
&& !(toHopper.getFilter().getWhiteList().isEmpty() && toHopper.getFilter().getBlackList().isEmpty())) {
&& !(toHopper.getFilter().getWhiteList().isEmpty() && toHopper.getFilter().getBlackList().isEmpty())) {
// this hopper has a filter with no rejection endpoint, so don't absorb disalowed items
// whitelist has priority
if (!toHopper.getFilter().getWhiteList().isEmpty()) {
// is this item on the whitelist?
if (!toHopper.getFilter().getWhiteList().stream().anyMatch(item -> Methods.isSimilarMaterial(toMove, item))) {
if (toHopper.getFilter().getWhiteList().stream().noneMatch(item -> Methods.isSimilarMaterial(toMove, item))) {
// nope!
continue;
}
@ -286,7 +318,7 @@ public class HopTask extends BukkitRunnable {
}
// Get amount to move.
int amountToMove = toMove.getAmount() < maxToMove ? toMove.getAmount() : maxToMove;
int amountToMove = Math.min(toMove.getAmount(), maxToMove);
// Create item that will be moved.
ItemStack itemToMove = toMove.clone();
@ -299,7 +331,10 @@ public class HopTask extends BukkitRunnable {
if (aboveCache != null) {
aboveCache.removeItems(itemToMove);
} else {
this.debt(itemToMove, amountToMove, aboveInvHolder);
if (isFarmItem)
com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager().getFarm(above).removeMaterial(itemToMove.getType(), amountToMove);
else
this.debt(itemToMove, amountToMove, aboveInvHolder);
}
break;
}
@ -352,7 +387,7 @@ public class HopTask extends BukkitRunnable {
StorageContainerCache.Cache cache = new StorageContainerCache.Cache(targetBlock.getType(), destinationInventory.getContents());
if (tryPush(hopper, hopperCache, cache, filterCache, maxToMove, blockedMaterials)) {
// update inventory and exit
if(cache.isDirty())
if (cache.isDirty())
destinationInventory.setContents(cache.cachedInventory);
return;
}
@ -377,8 +412,8 @@ public class HopTask extends BukkitRunnable {
// if we've gotten this far, check if we can push into a minecart
if (checkForMinecarts) {
for (InventoryHolder minecartInventory : hopper.getWorld().getNearbyEntities(pointingLocation.clone().add(0.5, 0.5, 0.5), 0.5, 0.5, 0.5)
.stream().filter(e -> e.getType() == EntityType.MINECART_CHEST || e.getType() == EntityType.MINECART_HOPPER)
.map(e -> (InventoryHolder) e).collect(Collectors.toSet())) {
.stream().filter(e -> e.getType() == EntityType.MINECART_CHEST || e.getType() == EntityType.MINECART_HOPPER)
.map(e -> (InventoryHolder) e).collect(Collectors.toSet())) {
StorageContainerCache.Cache cache = new StorageContainerCache.Cache(Material.CHEST, minecartInventory.getInventory().getContents());
if (tryPush(hopper, hopperCache, cache, filterCache, maxToMove, blockedMaterials)) {
if (cache.isDirty())
@ -390,10 +425,10 @@ public class HopTask extends BukkitRunnable {
}
private boolean tryPush(com.songoda.epichoppers.hopper.Hopper hopper,
StorageContainerCache.Cache hopperCache,
StorageContainerCache.Cache targetCache,
StorageContainerCache.Cache filterCache,
int maxToMove, Collection<Material> blockedMaterials) {
StorageContainerCache.Cache hopperCache,
StorageContainerCache.Cache targetCache,
StorageContainerCache.Cache filterCache,
int maxToMove, Collection<Material> blockedMaterials) {
// Loop through all of our hopper's item slots.
for (int i = 0; i < 5; i++) {
@ -403,11 +438,11 @@ public class HopTask extends BukkitRunnable {
// Can we check this item?
if ( // Ignore this one if the slot is empty
item == null
// Don't try to move items that we've added this round
|| (hopperCache.cacheChanged[i] && item.getAmount() - hopperCache.cacheAdded[i] < maxToMove)
// skip if blocked or voidlisted
|| blockedMaterials.contains(item.getType())
|| hopper.getFilter().getVoidList().stream().anyMatch(itemStack -> Methods.isSimilarMaterial(itemStack, item)))
// Don't try to move items that we've added this round
|| (hopperCache.cacheChanged[i] && item.getAmount() - hopperCache.cacheAdded[i] < maxToMove)
// skip if blocked or voidlisted
|| blockedMaterials.contains(item.getType())
|| hopper.getFilter().getVoidList().stream().anyMatch(itemStack -> Methods.isSimilarMaterial(itemStack, item)))
continue;
// Create item that will be moved.
@ -444,7 +479,7 @@ public class HopTask extends BukkitRunnable {
for (int i = 0; i < hopperContents.length; i++) {
final ItemStack item = hopperContents[i];
if (item != null && hopper.getFilter().getVoidList().stream().anyMatch(itemStack -> Methods.isSimilarMaterial(itemStack, item))) {
int amt = Math.min(0, item.getAmount() - maxToMove);
int amt = Math.max(0, item.getAmount() - maxToMove);
if (amt == 0) {
hopperCache.removeItem(i);
} else {
@ -456,8 +491,10 @@ public class HopTask extends BukkitRunnable {
}
}
}
/**
* Gets a set of slots that can be pulled from based on the given material
*
* @param material The material to get pullable slots for
* @return A set of valid pullable slots
*/
@ -490,6 +527,7 @@ public class HopTask extends BukkitRunnable {
/**
* Gets a random InventoryHolder from a collection of entities
* Only grabs InventoryHolders from StorageMinecarts and HopperMinecarts
*
* @param entities The collection of entities
* @return A random InventoryHolder if one exists, otherwise null
*/
@ -506,22 +544,17 @@ public class HopTask extends BukkitRunnable {
/**
* Checks if a given block is an EpicFarming farm item
*
* @param block The block to check
* @return true if the block is a farm item, otherwise false
*/
private boolean isFarmItem(Block block) {
return EpicHoppers.getInstance().isEpicFarming() && com.songoda.epicfarming.EpicFarmingPlugin.getInstance().getFarmManager().getFarm(block) != null;
return EpicHoppers.getInstance().isEpicFarming() && com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager().getFarm(block) != null;
}
/**
* Gets an EpicFarming block as an InventoryHolder
* Needed because EpicFarming doesn't natively support having an InventoryHolder for the farm item
*
* @param block The block to effectively attach an InventoryHolder to
* @return An InventoryHolder wrapping the EpicFarming inventory
*/
private InventoryHolder getEpicFarmingItemWrapped(Block block) {
return () -> com.songoda.epicfarming.EpicFarmingPlugin.getInstance().getFarmManager().getFarm(block).getInventory();
private ItemStack[] getFarmContents(Block block) {
return com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager()
.getFarm(block).getItems().toArray(new ItemStack[0]);
}
}

View File

@ -110,7 +110,7 @@ public class Methods {
&& p.getItemInHand().getType() != Material.ENCHANTED_BOOK
&& p.getItemInHand().getItemMeta().hasLore()) {
for (String str : p.getItemInHand().getItemMeta().getLore()) {
if (str.equals(Methods.formatText("&7Sync Touch")) || str.equals(Methods.formatText("&aSync Touch"))) {
if (str.contains(Methods.formatText("&7Sync Touch")) || str.contains(Methods.formatText("&aSync Touch"))) {
return true;
}
}
@ -365,7 +365,52 @@ public class Methods {
public static String makeReadable(Long time) {
if (time == null)
return "";
return String.format("%d hour(s), %d min(s), %d sec(s)", TimeUnit.MILLISECONDS.toHours(time), TimeUnit.MILLISECONDS.toMinutes(time) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(time)), TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time)));
StringBuilder sb = new StringBuilder();
long days = TimeUnit.MILLISECONDS.toDays(time);
long hours = TimeUnit.MILLISECONDS.toHours(time) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(time));
long minutes = TimeUnit.MILLISECONDS.toMinutes(time) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(time));
long seconds = TimeUnit.MILLISECONDS.toSeconds(time) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(time));
if (days != 0L)
sb.append(" ").append(days).append("d");
if (hours != 0L)
sb.append(" ").append(hours).append("h");
if (minutes != 0L)
sb.append(" ").append(minutes).append("m");
if (seconds != 0L)
sb.append(" ").append(seconds).append("s");
return sb.toString().trim();
}
public static long parseTime(String input) {
long result = 0;
StringBuilder number = new StringBuilder();
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isDigit(c)) {
number.append(c);
} else if (Character.isLetter(c) && (number.length() > 0)) {
result += convert(Integer.parseInt(number.toString()), c);
number = new StringBuilder();
}
}
return result;
}
private static long convert(long value, char unit) {
switch (unit) {
case 'd':
return value * 1000 * 60 * 60 * 24;
case 'h':
return value * 1000 * 60 * 60;
case 'm':
return value * 1000 * 60;
case 's':
return value * 1000;
}
return 0;
}
/**

View File

@ -33,7 +33,7 @@ public class MySQLDatabase {
"\t`whitelist` TEXT NULL,\n" +
"\t`blacklist` TEXT NULL,\n" +
"\t`void` TEXT NULL,\n" +
"\t`black` TEXT NULL,\n" +
"\t`black` TEXT NULL\n" +
")");
connection.createStatement().execute("CREATE TABLE IF NOT EXISTS `" + instance.getConfig().getString("Database.Prefix") + "boosts` (\n" +

View File

@ -5,7 +5,10 @@ import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Chest;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
@ -18,21 +21,80 @@ public class StorageContainerCache {
private final static Map<Block, Cache> inventoryCache = new HashMap<>();
// need to get the topmost inventory for a double chest, and save as that block
public static Cache getCachedInventory(Block b) {
Cache cache = inventoryCache.get(b);
if (cache == null) {
Material type = b.getType();
if(type == Material.CHEST || type == Material.TRAPPED_CHEST) {
Block b2 = findAdjacentDoubleChest(b);
//System.out.println("Adjacent to " + b + " = " + b2);
if(b2 != null && (cache = inventoryCache.get(b2)) != null) {
return cache;
}
}
BlockState blockState = b.getState();
if (blockState instanceof InventoryHolder) {
//System.out.println("Load " + b.getLocation());
inventoryCache.put(b, cache = new Cache(b, ((InventoryHolder) blockState).getInventory().getContents()));
}
}
return cache;
}
/**
* Look for a double chest adjacent to a chest
*
* @param block
* @return
*/
public static Block findAdjacentDoubleChest(Block block) {
if(EpicHoppers.getInstance().isServerVersionAtLeast(ServerVersion.V1_13)) {
final BlockData d = block.getBlockData();
if (d instanceof Chest) {
final Chest c = (Chest) d;
if(c.getType() != Chest.Type.SINGLE) {
// this is a double chest - check the other chest for registration data
Block other = null;
switch(c.getFacing()) {
case SOUTH:
other = block.getRelative(c.getType() != Chest.Type.RIGHT ? BlockFace.WEST : BlockFace.EAST);
break;
case NORTH:
other = block.getRelative(c.getType() != Chest.Type.RIGHT ? BlockFace.EAST : BlockFace.WEST);
break;
case EAST:
other = block.getRelative(c.getType() != Chest.Type.RIGHT ? BlockFace.SOUTH : BlockFace.NORTH);
break;
case WEST:
other = block.getRelative(c.getType() != Chest.Type.RIGHT ? BlockFace.NORTH : BlockFace.SOUTH);
}
// double-check
if (other != null && other.getType() == block.getType()) {
return other;
}
}
}
} else {
// legacy check
Material material = block.getType();
BlockFace[] faces = new BlockFace[]{BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST};
for (BlockFace face : faces) {
Block adjacentBlock = block.getRelative(face);
if (adjacentBlock.getType() == material) {
return adjacentBlock;
}
}
}
return null;
}
public static void update() {
inventoryCache.entrySet().stream()
.filter(e -> e.getValue().dirty)
.forEach(e -> {
//System.out.println("Update " + e.getKey().getLocation());
// setContents makes a copy of every item whether it's needed or not
//((InventoryHolder) e.getKey().getState()).getInventory().setContents(e.getValue().cachedInventory);
// so let's only update what needs to be updated.
@ -63,7 +125,9 @@ public class StorageContainerCache {
this.type = type;
this.cachedInventory = cachedInventory;
this.cacheChanged = new boolean[cachedInventory.length];
this.cacheAdded = new int[cachedInventory.length];
}
public Cache(Block b, ItemStack[] cachedInventory) {
this.block = b;
this.type = b.getType();
@ -208,6 +272,7 @@ public class StorageContainerCache {
else
check[3] = true;
break;
}
case "SMOKER":
case "BLAST_FURNACE":