Reworked how custom containers are handled.

This commit is contained in:
Fernando Pettinelli 2021-12-08 22:35:57 -03:00
parent 81320f2b3b
commit 6044aa3077
11 changed files with 327 additions and 124 deletions

View File

@ -20,6 +20,7 @@ import com.songoda.epichoppers.commands.CommandBoost;
import com.songoda.epichoppers.commands.CommandGive;
import com.songoda.epichoppers.commands.CommandReload;
import com.songoda.epichoppers.commands.CommandSettings;
import com.songoda.epichoppers.containers.ContainerManager;
import com.songoda.epichoppers.database.DataManager;
import com.songoda.epichoppers.database.migrations._1_InitialMigration;
import com.songoda.epichoppers.hopper.teleport.TeleportHandler;
@ -68,15 +69,13 @@ public class EpicHoppers extends SongodaPlugin {
private LevelManager levelManager;
private BoostManager boostManager;
private PlayerDataManager playerDataManager;
private ContainerManager containerManager;
private TeleportHandler teleportHandler;
private DatabaseConnector databaseConnector;
private DataManager dataManager;
private boolean epicfarming = false;
private boolean advancedchests = false;
public static EpicHoppers getInstance() {
return INSTANCE;
}
@ -122,6 +121,7 @@ public class EpicHoppers extends SongodaPlugin {
this.hopperManager = new HopperManager();
this.playerDataManager = new PlayerDataManager();
this.containerManager = new ContainerManager(this);
this.boostManager = new BoostManager();
// Database stuff, go!
@ -147,10 +147,6 @@ public class EpicHoppers extends SongodaPlugin {
pluginManager.registerEvents(new InteractListeners(this), this);
pluginManager.registerEvents(new InventoryListeners(), this);
// Check for epicfarming
if (pluginManager.isPluginEnabled("EpicFarming")) epicfarming = true;
if (pluginManager.isPluginEnabled("AdvancedChests")) advancedchests = true;
// Start auto save
int saveInterval = Settings.AUTOSAVE.getInt() * 60 * 20;
Bukkit.getScheduler().runTaskTimerAsynchronously(this, this::saveModules, saveInterval, saveInterval);
@ -301,11 +297,7 @@ public class EpicHoppers extends SongodaPlugin {
return databaseConnector;
}
public boolean isEpicFarming() {
return epicfarming;
}
public boolean isAdvancedChests() {
return advancedchests;
public ContainerManager getContainerManager() {
return containerManager;
}
}

View File

@ -0,0 +1,54 @@
package com.songoda.epichoppers.containers;
import com.songoda.epichoppers.EpicHoppers;
import com.songoda.epichoppers.containers.impl.AdvancedChestImplementation;
import com.songoda.epichoppers.containers.impl.EpicFarmingImplementation;
import com.songoda.epichoppers.containers.impl.FabledSkyBlockImplementation;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.plugin.PluginManager;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class ContainerManager {
private final EpicHoppers plugin;
private final Set<IContainer> customContainers;
public ContainerManager(EpicHoppers plugin) {
this.plugin = plugin;
this.customContainers = new HashSet<>();
registerCustomContainerImplementation("AdvancedChests", new AdvancedChestImplementation());
registerCustomContainerImplementation("EpicFarming", new EpicFarmingImplementation());
registerCustomContainerImplementation("FabledSkyBlock", new FabledSkyBlockImplementation());
}
public Set<IContainer> getCustomContainerImplementations() {
return Collections.unmodifiableSet(customContainers);
}
public void registerCustomContainerImplementation(String requiredPlugin, IContainer container) {
PluginManager pluginManager = Bukkit.getPluginManager();
if (requiredPlugin != null && pluginManager.isPluginEnabled(requiredPlugin)) {
customContainers.add(container);
}
}
public void registerCustomContainerImplementation(IContainer container) {
registerCustomContainerImplementation(null, container);
}
public CustomContainer getCustomContainer(Block block) {
for (IContainer container : customContainers) {
CustomContainer customContainer = container.getCustomContainer(block);
if (customContainer.isContainer()) {
return customContainer;
}
}
return null;
}
}

View File

@ -0,0 +1,17 @@
package com.songoda.epichoppers.containers;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
public abstract class CustomContainer {
private final Block block;
public CustomContainer(Block block) {
this.block = block;
}
public abstract boolean addToContainer(ItemStack itemToMove);
public abstract ItemStack[] getItems();
public abstract void removeFromContainer(ItemStack itemToMove, int amountToMove);
public abstract boolean isContainer();
}

View File

@ -0,0 +1,8 @@
package com.songoda.epichoppers.containers;
import org.bukkit.block.Block;
public interface IContainer {
CustomContainer getCustomContainer(Block block);
}

View File

@ -0,0 +1,54 @@
package com.songoda.epichoppers.containers.impl;
import com.songoda.epichoppers.containers.CustomContainer;
import com.songoda.epichoppers.containers.IContainer;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
import us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI;
import us.lynuxcraft.deadsilenceiv.advancedchests.chest.AdvancedChest;
public class AdvancedChestImplementation implements IContainer {
@Override
public CustomContainer getCustomContainer(Block block) {
return new Container(block);
}
class Container extends CustomContainer {
private final AdvancedChest advancedChest;
public Container(Block block) {
super(block);
this.advancedChest = AdvancedChestsAPI.getChestManager().getAdvancedChest(block.getLocation());
}
@Override
public boolean addToContainer(ItemStack itemToMove) {
return AdvancedChestsAPI.addItemToChest(advancedChest, itemToMove);
}
@Override
public ItemStack[] getItems() {
return advancedChest.getAllItems().toArray(new ItemStack[0]);
}
@Override
public void removeFromContainer(ItemStack itemToMove, int amountToMove) {
for (ItemStack item : advancedChest.getAllItems()) {
if (item == null) return;
if (itemToMove.getType() == item.getType()) {
item.setAmount(item.getAmount() - amountToMove);
if (item.getAmount() <= 0)
advancedChest.getAllItems().remove(item);
return;
}
}
}
@Override
public boolean isContainer() {
return advancedChest != null;
}
}
}

View File

@ -0,0 +1,52 @@
package com.songoda.epichoppers.containers.impl;
import com.songoda.epicfarming.EpicFarming;
import com.songoda.epicfarming.core.compatibility.CompatibleMaterial;
import com.songoda.epicfarming.farming.Farm;
import com.songoda.epichoppers.containers.CustomContainer;
import com.songoda.epichoppers.containers.IContainer;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
public class EpicFarmingImplementation implements IContainer {
@Override
public CustomContainer getCustomContainer(Block block) {
return new Container(block);
}
class Container extends CustomContainer {
private final Farm farm;
public Container(Block block) {
super(block);
this.farm = EpicFarming.getInstance().getFarmManager().getFarm(block);
}
@Override
public boolean addToContainer(ItemStack itemToMove) {
if (!farm.willFit(itemToMove)) {
return false;
}
farm.addItem(itemToMove);
return true;
}
@Override
public ItemStack[] getItems() {
return farm.getItems()
.stream().filter(i -> CompatibleMaterial.getMaterial(i) != CompatibleMaterial.BONE_MEAL)
.toArray(ItemStack[]::new);
}
@Override
public void removeFromContainer(ItemStack itemToMove, int amountToMove) {
farm.removeMaterial(itemToMove.getType(), amountToMove);
}
@Override
public boolean isContainer() {
return farm != null;
}
}
}

View File

@ -0,0 +1,66 @@
package com.songoda.epichoppers.containers.impl;
import com.songoda.epichoppers.containers.CustomContainer;
import com.songoda.epichoppers.containers.IContainer;
import com.songoda.skyblock.SkyBlock;
import com.songoda.skyblock.core.compatibility.CompatibleMaterial;
import com.songoda.skyblock.stackable.Stackable;
import com.songoda.skyblock.stackable.StackableManager;
import org.bukkit.block.Block;
import org.bukkit.inventory.ItemStack;
public class FabledSkyBlockImplementation implements IContainer {
@Override
public CustomContainer getCustomContainer(Block block) {
return new Container(block);
}
class Container extends CustomContainer {
private final Stackable stackable;
public Container(Block block) {
super(block);
StackableManager stackableManager = SkyBlock.getInstance().getStackableManager();
CompatibleMaterial compatibleMaterial = CompatibleMaterial.getMaterial(block);
this.stackable = stackableManager.getStack(block.getLocation(), compatibleMaterial);
}
@Override
public boolean addToContainer(ItemStack itemToMove) {
if (CompatibleMaterial.getMaterial(itemToMove) != stackable.getMaterial()) {
return false;
}
stackable.addOne();
if (stackable.isMaxSize()) {
stackable.setSize(stackable.getMaxSize());
return false;
}
return true;
}
@Override
public ItemStack[] getItems() {
ItemStack[] array = { new ItemStack(stackable.getMaterial().getMaterial(), stackable.getSize()) };
return array;
}
@Override
public void removeFromContainer(ItemStack itemToMove, int amountToMove) {
if (CompatibleMaterial.getMaterial(itemToMove) != stackable.getMaterial()) {
return;
}
stackable.setSize(stackable.getSize() - amountToMove);
}
@Override
public boolean isContainer() {
return stackable != null;
}
}
}

View File

@ -14,12 +14,12 @@ import com.songoda.epichoppers.player.PlayerData;
import com.songoda.epichoppers.settings.Settings;
import com.songoda.epichoppers.utils.CostType;
import com.songoda.epichoppers.utils.Methods;
import org.bukkit.Bukkit;
import org.bukkit.GameMode;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.HashMap;
@ -81,6 +81,19 @@ public class Hopper {
activePlayer.closeInventory();
}
public void dropItems() {
Inventory inventory = ((InventoryHolder) location.getBlock().getState()).getInventory();
World world = location.getWorld();
for (ItemStack itemStack : inventory.getContents()) {
if (itemStack == null || itemStack.getType() == Material.AIR) {
continue;
}
world.dropItemNaturally(location, itemStack);
}
}
public void upgrade(Player player, CostType type) {
EpicHoppers plugin = EpicHoppers.getInstance();
if (!plugin.getLevelManager().getLevels().containsKey(this.level.getLevel() + 1)) return;
@ -125,11 +138,8 @@ public class Hopper {
}
Location loc = location.clone().add(.5, .5, .5);
if (!Settings.UPGRADE_PARTICLE_TYPE.getString().trim().isEmpty()) {
CompatibleParticleHandler.spawnParticles(
CompatibleParticleHandler.ParticleType.getParticle(Settings.UPGRADE_PARTICLE_TYPE.getString()),
loc, 100, .5, .5, .5);
}
CompatibleParticleHandler.spawnParticles(CompatibleParticleHandler.ParticleType.getParticle(Settings.UPGRADE_PARTICLE_TYPE.getString()),
loc, 100, .5, .5, .5);
if (plugin.getLevelManager().getHighestLevel() != level) {
player.playSound(player.getLocation(), CompatibleSound.ENTITY_PLAYER_LEVELUP.getSound(), 0.6F, 15.0F);

View File

@ -65,8 +65,8 @@ 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.EpicFarming.getInstance().getFarmManager().getFarm(above) != null)
// Don't break farm items from custom containers
if (plugin.getContainerManager().getCustomContainer(above) != null)
return;
// don't break blacklisted blocks, fluids, or containers
@ -92,18 +92,14 @@ public class ModuleBlockBreak extends Module {
float yy = (float) (0 + (Math.random() * .5));
float zz = (float) (0 + (Math.random() * .5));
Particle particle = null;
if (!Settings.BLOCKBREAK_PARTICLE.getString().trim().isEmpty()) {
try {
particle = Particle.valueOf(Settings.BLOCKBREAK_PARTICLE.getString());
} catch (Exception ignore) {
particle = Particle.LAVA;
}
Particle particle;
try {
particle = Particle.valueOf(Settings.BLOCKBREAK_PARTICLE.getString());
} catch (Exception e) {
particle = Particle.LAVA;
}
if (particle != null) {
above.getWorld().spawnParticle(particle, locationAbove, 15, xx, yy, zz);
}
above.getWorld().spawnParticle(particle, locationAbove, 15, xx, yy, zz);
}
boolean waterlogged = false;

View File

@ -1,5 +1,6 @@
package com.songoda.epichoppers.listeners;
import com.songoda.core.compatibility.ServerVersion;
import com.songoda.epichoppers.EpicHoppers;
import com.songoda.epichoppers.api.events.HopperBreakEvent;
import com.songoda.epichoppers.api.events.HopperPlaceEvent;
@ -10,6 +11,7 @@ import com.songoda.epichoppers.settings.Settings;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -26,6 +28,7 @@ import org.bukkit.permissions.PermissionAttachmentInfo;
public class BlockListeners implements Listener {
private final EpicHoppers plugin;
private static final boolean hasMinHeight = ServerVersion.isServerVersionAtLeast(ServerVersion.V1_16);
public BlockListeners(EpicHoppers plugin) {
this.plugin = plugin;
@ -90,7 +93,7 @@ public class BlockListeners implements Listener {
int count = 0;
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < c.getWorld().getMaxHeight(); y++) {
for (int y = getMinHeight(c.getWorld()); y < c.getWorld().getMaxHeight(); y++) {
if (c.getBlock(x, y, z).getType() == Material.HOPPER) count++;
}
}
@ -125,6 +128,8 @@ public class BlockListeners implements Listener {
event.setCancelled(true);
ItemStack item = plugin.newHopperItem(level);
hopper.dropItems();
event.getBlock().setType(Material.AIR);
event.getBlock().getLocation().getWorld().dropItemNaturally(event.getBlock().getLocation(), item);
}
@ -146,4 +151,8 @@ public class BlockListeners implements Listener {
plugin.getPlayerDataManager().getPlayerData(player).setSyncType(null);
}
public int getMinHeight(World world) {
return hasMinHeight ? world.getMinHeight() : 0;
}
}

View File

@ -1,8 +1,8 @@
package com.songoda.epichoppers.tasks;
import com.songoda.core.compatibility.CompatibleMaterial;
import com.songoda.epichoppers.EpicHoppers;
import com.songoda.epichoppers.boost.BoostData;
import com.songoda.epichoppers.containers.CustomContainer;
import com.songoda.epichoppers.hopper.levels.modules.Module;
import com.songoda.epichoppers.hopper.levels.modules.ModuleAutoCrafting;
import com.songoda.epichoppers.settings.Settings;
@ -23,7 +23,6 @@ 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;
@ -40,18 +39,13 @@ import java.util.stream.IntStream;
public class HopTask extends BukkitRunnable {
// Hop to the bop to the be bop top.
private EpicHoppers plugin;
private final int hopTicks;
private final boolean hasFabledSkyBlock;
private final Plugin fabledSkyblockPlugin;
public HopTask(EpicHoppers plugin) {
this.plugin = plugin;
this.hopTicks = Math.max(1, Settings.HOP_TICKS.getInt() / 2); // Purposeful integer division. Don't go below 1.
this.runTaskTimer(plugin, 0, 2);
this.hasFabledSkyBlock = (fabledSkyblockPlugin = Bukkit.getPluginManager().getPlugin("FabledSkyBlock")) != null;
}
@Override
@ -139,55 +133,22 @@ public class HopTask extends BukkitRunnable {
if (!doProcess)
continue;
// Support for FabledSkyBlock stackables.
if (this.hasFabledSkyBlock) {
com.songoda.skyblock.stackable.StackableManager stackableManager = ((com.songoda.skyblock.SkyBlock) fabledSkyblockPlugin).getStackableManager();
if (stackableManager != null && stackableManager.isStacked(pointingLocation)) {
Block pointingBlock = pointingLocation.getBlock();
com.songoda.skyblock.core.compatibility.CompatibleMaterial compatibleMaterial = com.songoda.skyblock.core.compatibility.CompatibleMaterial.getMaterial(pointingBlock);
com.songoda.skyblock.stackable.Stackable stackable = stackableManager.getStack(pointingLocation, compatibleMaterial);
for (int i = 0; i < 5; i++) {
final ItemStack item = hopperCache.cachedInventory[i];
if (item == null) {
continue;
}
if (com.songoda.skyblock.core.compatibility.CompatibleMaterial.getMaterial(item) == compatibleMaterial) {
stackable.addOne();
if (item.getAmount() == 1) {
hopperCache.removeItem(i);
} else {
item.setAmount(item.getAmount() - 1);
hopperCache.dirty = hopperCache.cacheChanged[i] = true;
}
break;
}
CustomContainer container = plugin.getContainerManager().getCustomContainer(pointingLocation.getBlock());
if (container != null) {
for (int i = 0; i < 5; i++) {
final ItemStack item = hopperCache.cachedInventory[i];
if (item == null) {
continue;
}
}
}
if (plugin.isAdvancedChests()) {
us.lynuxcraft.deadsilenceiv.advancedchests.chest.AdvancedChest chest = us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI.getChestManager().getAdvancedChest(pointingLocation);
if (chest != null) {
for (int i = 0; i < 5; i++) {
final ItemStack item = hopperCache.cachedInventory[i];
if (item == null) {
continue;
}
if (us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI.hasSpaceForItem(chest, item)) {
us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI.addItemToChest(chest, item);
if (item.getAmount() == 1) {
hopperCache.removeItem(i);
} else {
item.setAmount(item.getAmount() - 1);
hopperCache.dirty = hopperCache.cacheChanged[i] = true;
}
break;
if (container.addToContainer(item)) {
if (item.getAmount() == 1) {
hopperCache.removeItem(i);
} else {
item.setAmount(item.getAmount() - 1);
hopperCache.dirty = hopperCache.cacheChanged[i] = true;
}
break;
}
}
}
@ -234,13 +195,15 @@ public class HopTask extends BukkitRunnable {
}
private void pullItemsFromContainers(com.songoda.epichoppers.hopper.Hopper toHopper, StorageContainerCache.Cache hopperCache, int maxToMove) {
// Grab items from the container above (includes storage/hopper minecarts and EpicFarming farm items)
// Grab items from the container above (includes storage/hopper minecarts, EpicFarming farm items and AdvancedChests chest)
// If the container above is a hopper, ignore it if it's pointing down
Block above = toHopper.getBlock().getRelative(BlockFace.UP);
boolean isFarmItem = false;
Collection<Entity> nearbyEntities = null;
StorageContainerCache.Cache aboveCache = null;
if ((isFarmItem = this.isFarmItem(above))
CustomContainer container = plugin.getContainerManager().getCustomContainer(above);
if ((container != null)
|| (above.getType() != Material.AIR)
&& (above.getType() != Material.HOPPER || HopperDirection.getDirection(above.getState().getRawData()) != HopperDirection.DOWN)
&& (aboveCache = StorageContainerCache.getCachedInventory(above)) != null
@ -254,9 +217,9 @@ public class HopTask extends BukkitRunnable {
pullableSlots = this.getPullableSlots(above.getType(), aboveCache.cachedInventory.length - 1);
contents = aboveCache.cachedInventory;
aboveInvHolder = null;
} else if (isFarmItem) {
} else if (container != null) {
aboveInvHolder = null;
contents = getFarmContents(above);
contents = container.getItems();
pullableSlots = IntStream.rangeClosed(0, contents.length - 1).toArray();
} else {
if ((aboveInvHolder = this.getRandomInventoryHolderFromEntities(nearbyEntities)) == null
@ -322,10 +285,11 @@ public class HopTask extends BukkitRunnable {
if (aboveCache != null) {
aboveCache.removeItems(itemToMove);
} else {
if (isFarmItem)
com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager().getFarm(above).removeMaterial(itemToMove.getType(), amountToMove);
else
if (container != null)
container.removeFromContainer(itemToMove, amountToMove);
else {
this.debt(itemToMove, amountToMove, aboveInvHolder);
}
}
break;
}
@ -388,12 +352,9 @@ public class HopTask extends BukkitRunnable {
continue;
}
if (plugin.isAdvancedChests()) {
us.lynuxcraft.deadsilenceiv.advancedchests.chest.AdvancedChest chest = us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI.getChestManager().getAdvancedChest(targetBlock.getLocation());
if (chest != null) {
addToAdvancedChest(hopper, hopperCache, chest, filterCache, maxToMove, blockedMaterials);
return;
}
CustomContainer container = plugin.getContainerManager().getCustomContainer(targetLocation.getBlock());
if (container != null && tryPushCustomContainer(hopper, hopperCache, container, filterCache, maxToMove, blockedMaterials)) {
return;
}
// Is this a storage container?
@ -424,11 +385,11 @@ public class HopTask extends BukkitRunnable {
}
}
private boolean addToAdvancedChest(com.songoda.epichoppers.hopper.Hopper hopper,
StorageContainerCache.Cache hopperCache,
us.lynuxcraft.deadsilenceiv.advancedchests.chest.AdvancedChest chest,
StorageContainerCache.Cache filterCache,
int maxToMove, Collection<Material> blockedMaterials) {
private boolean tryPushCustomContainer(com.songoda.epichoppers.hopper.Hopper hopper,
StorageContainerCache.Cache hopperCache,
CustomContainer container,
StorageContainerCache.Cache filterCache,
int maxToMove, Collection<Material> blockedMaterials) {
for (int i = 0; i < 5; i++) {
// Get potential item to move.
ItemStack item = hopperCache.cachedInventory[i];
@ -462,7 +423,7 @@ public class HopTask extends BukkitRunnable {
}
// Add item to container and return on success.
if (us.lynuxcraft.deadsilenceiv.advancedchests.AdvancedChestsAPI.addItemToChest(chest, itemToMove)) {
if (container.addToContainer(itemToMove)) {
hopperCache.removeItems(itemToMove);
return true;
}
@ -587,20 +548,4 @@ public class HopTask extends BukkitRunnable {
return inventoryHolders.get(0);
return inventoryHolders.get(ThreadLocalRandom.current().nextInt(inventoryHolders.size()));
}
/**
* 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 plugin.isEpicFarming() && com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager().getFarm(block) != null;
}
private ItemStack[] getFarmContents(Block block) {
return com.songoda.epicfarming.EpicFarming.getInstance().getFarmManager().getFarm(block).getItems()
.stream().filter(i -> CompatibleMaterial.getMaterial(i) != CompatibleMaterial.BONE_MEAL)
.toArray(ItemStack[]::new);
}
}