From eff46ed7386bc827ee2d007568ab5ac481a1ee7e Mon Sep 17 00:00:00 2001 From: Auxilor Date: Fri, 18 Dec 2020 14:35:03 +0000 Subject: [PATCH] Reworked FastCollatedDropQueue into cleaner system --- .../command/commands/CommandEcodebug.java | 8 +- .../ecoenchants/normal/InfernalTouch.java | 6 - .../ecoenchants/normal/Telekinesis.java | 6 - .../ecoenchants/util/internal/DropQueue.java | 82 ++------- .../ecoenchants/util/internal/Loader.java | 23 ++- .../internal/drops/AbstractDropQueue.java | 66 +++++++ .../{ => drops}/FastCollatedDropQueue.java | 55 ++++-- .../internal/drops/InternalDropQueue.java | 168 ++++++++++++++++++ 8 files changed, 308 insertions(+), 106 deletions(-) create mode 100644 Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/AbstractDropQueue.java rename Plugin/src/main/java/com/willfp/ecoenchants/util/internal/{ => drops}/FastCollatedDropQueue.java (67%) create mode 100644 Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/InternalDropQueue.java diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/command/commands/CommandEcodebug.java b/Plugin/src/main/java/com/willfp/ecoenchants/command/commands/CommandEcodebug.java index 64080e3c..e200671e 100644 --- a/Plugin/src/main/java/com/willfp/ecoenchants/command/commands/CommandEcodebug.java +++ b/Plugin/src/main/java/com/willfp/ecoenchants/command/commands/CommandEcodebug.java @@ -5,8 +5,8 @@ import com.willfp.ecoenchants.command.AbstractCommand; import com.willfp.ecoenchants.display.EnchantmentCache; import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchants; -import com.willfp.ecoenchants.util.internal.FastCollatedDropQueue; import com.willfp.ecoenchants.util.internal.Logger; +import com.willfp.ecoenchants.util.internal.drops.FastCollatedDropQueue; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.enchantments.Enchantment; @@ -14,7 +14,11 @@ import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import java.lang.reflect.Field; -import java.util.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; @SuppressWarnings("unchecked") diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/InfernalTouch.java b/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/InfernalTouch.java index 60e3eab0..957877ef 100644 --- a/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/InfernalTouch.java +++ b/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/InfernalTouch.java @@ -4,7 +4,6 @@ import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.util.EnchantChecks; import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager; import com.willfp.ecoenchants.util.internal.DropQueue; -import com.willfp.ecoenchants.util.internal.FastCollatedDropQueue; import com.willfp.ecoenchants.util.tuplets.Pair; import org.bukkit.Bukkit; import org.bukkit.GameMode; @@ -98,11 +97,6 @@ public class InfernalTouch extends EcoEnchant { event.getItems().clear(); - if(FastCollatedDropQueue.use()) { - FastCollatedDropQueue.collateDrop(player, drops, experience.get(), block.getLocation()); - return; - } - new DropQueue(player) .setLocation(block.getLocation()) .addItems(drops) diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Telekinesis.java b/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Telekinesis.java index 7e14940e..3397472b 100644 --- a/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Telekinesis.java +++ b/Plugin/src/main/java/com/willfp/ecoenchants/enchantments/ecoenchants/normal/Telekinesis.java @@ -8,7 +8,6 @@ import com.willfp.ecoenchants.events.entitydeathbyentity.EntityDeathByEntityEven import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager; import com.willfp.ecoenchants.nms.TridentStack; import com.willfp.ecoenchants.util.internal.DropQueue; -import com.willfp.ecoenchants.util.internal.FastCollatedDropQueue; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; @@ -56,11 +55,6 @@ public class Telekinesis extends EcoEnchant { event.getItems().clear(); - if(FastCollatedDropQueue.use()) { - FastCollatedDropQueue.collateDrop(player, drops, 0, block.getLocation()); - return; - } - new DropQueue(player) .setLocation(block.getLocation()) .addItems(drops) diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/DropQueue.java b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/DropQueue.java index 0346bf72..a467b067 100644 --- a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/DropQueue.java +++ b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/DropQueue.java @@ -1,34 +1,21 @@ package com.willfp.ecoenchants.util.internal; import com.willfp.ecoenchants.enchantments.EcoEnchants; -import com.willfp.ecoenchants.enchantments.util.EnchantChecks; -import com.willfp.ecoenchants.util.NumberUtils; -import org.bukkit.*; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.ExperienceOrb; +import com.willfp.ecoenchants.util.internal.drops.AbstractDropQueue; +import com.willfp.ecoenchants.util.internal.drops.FastCollatedDropQueue; +import com.willfp.ecoenchants.util.internal.drops.InternalDropQueue; +import org.bukkit.Location; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerExpChangeEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.util.Vector; -import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; -import java.util.List; /** * All drops generated from enchantments should be sent through a {@link DropQueue} * Interacts with {@link EcoEnchants#TELEKINESIS} */ public class DropQueue { - private final List items; - private int xp; - private final Player player; - private Location loc; - private boolean hasTelekinesis = false; - private ItemStack item; - - private static boolean useOrb; + private final AbstractDropQueue handle; /** * Create {@link DropQueue} linked to player @@ -36,11 +23,7 @@ public class DropQueue { * @param player The player */ public DropQueue(Player player) { - this.items = new ArrayList<>(); - this.xp = 0; - this.player = player; - this.loc = player.getLocation(); - this.item = player.getInventory().getItemInMainHand(); + handle = FastCollatedDropQueue.use() ? new FastCollatedDropQueue(player) : new InternalDropQueue(player); } /** @@ -51,7 +34,7 @@ public class DropQueue { * @return The DropQueue */ public DropQueue addItem(ItemStack item) { - this.items.add(item); + handle.addItem(item); return this; } @@ -63,7 +46,7 @@ public class DropQueue { * @return The DropQueue */ public DropQueue addItems(Collection itemStacks) { - this.items.addAll(itemStacks); + handle.addItems(itemStacks); return this; } @@ -75,7 +58,7 @@ public class DropQueue { * @return The DropQueue */ public DropQueue addXP(int amount) { - this.xp += amount; + handle.addXP(amount); return this; } @@ -87,7 +70,7 @@ public class DropQueue { * @return The DropQueue */ public DropQueue setLocation(Location l) { - this.loc = l; + handle.setLocation(l); return this; } @@ -97,7 +80,7 @@ public class DropQueue { * @return The DropQueue */ public DropQueue forceTelekinesis() { - this.hasTelekinesis = true; + handle.forceTelekinesis(); return this; } @@ -110,7 +93,7 @@ public class DropQueue { * @return The DropQueue */ public DropQueue setItem(ItemStack item) { - this.item = item; + handle.setItem(item); return this; } @@ -118,45 +101,6 @@ public class DropQueue { * Push the queue */ public void push() { - if(!hasTelekinesis) hasTelekinesis = EnchantChecks.item(item, EcoEnchants.TELEKINESIS); - if(hasTelekinesis && !EcoEnchants.TELEKINESIS.isEnabled()) hasTelekinesis = false; - - World world = loc.getWorld(); - assert world != null; - - if(hasTelekinesis) { - HashMap leftover = player.getInventory().addItem(items.toArray(new ItemStack[]{})); - for(ItemStack drop : leftover.values()) { - world.dropItemNaturally(loc.add(0.5, 0, 0.5), drop).setVelocity(new Vector()); - } - if (xp > 0) { - PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, xp); - Bukkit.getPluginManager().callEvent(event); - if (useOrb) { - ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(player.getLocation().add(0, 0.2, 0), EntityType.EXPERIENCE_ORB); - orb.setVelocity(new Vector(0, 0, 0)); - orb.setExperience(event.getAmount()); - } else { - player.giveExp(event.getAmount()); - player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.AMBIENT, 1f, (float) NumberUtils.randFloat(0.7, 1.2)); - } - } - } else { - for (ItemStack drop : items) { - world.dropItemNaturally(loc.add(0.5, 0, 0.5), drop).setVelocity(new Vector()); - } - if (xp > 0) { - ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(loc, EntityType.EXPERIENCE_ORB); - orb.setExperience(xp); - } - } - } - - public static void update() { - useOrb = EcoEnchants.TELEKINESIS.getConfig().getBool(EcoEnchants.CONFIG_LOCATION + "use-orb"); - } - - static { - update(); + handle.push(); } } diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/Loader.java b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/Loader.java index f955cd7c..f4fe2fd2 100644 --- a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/Loader.java +++ b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/Loader.java @@ -8,7 +8,11 @@ import com.willfp.ecoenchants.command.tabcompleters.TabCompleterEnchantinfo; import com.willfp.ecoenchants.config.ConfigManager; import com.willfp.ecoenchants.display.EnchantDisplay; import com.willfp.ecoenchants.display.EnchantmentCache; -import com.willfp.ecoenchants.display.packets.*; +import com.willfp.ecoenchants.display.packets.PacketChat; +import com.willfp.ecoenchants.display.packets.PacketOpenWindowMerchant; +import com.willfp.ecoenchants.display.packets.PacketSetCreativeSlot; +import com.willfp.ecoenchants.display.packets.PacketSetSlot; +import com.willfp.ecoenchants.display.packets.PacketWindowItems; import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchants; import com.willfp.ecoenchants.enchantments.meta.EnchantmentRarity; @@ -29,7 +33,12 @@ import com.willfp.ecoenchants.integrations.anticheat.plugins.AnticheatMatrix; import com.willfp.ecoenchants.integrations.anticheat.plugins.AnticheatNCP; import com.willfp.ecoenchants.integrations.anticheat.plugins.AnticheatSpartan; import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager; -import com.willfp.ecoenchants.integrations.antigrief.plugins.*; +import com.willfp.ecoenchants.integrations.antigrief.plugins.AntigriefFactionsUUID; +import com.willfp.ecoenchants.integrations.antigrief.plugins.AntigriefGriefPrevention; +import com.willfp.ecoenchants.integrations.antigrief.plugins.AntigriefKingdoms; +import com.willfp.ecoenchants.integrations.antigrief.plugins.AntigriefLands; +import com.willfp.ecoenchants.integrations.antigrief.plugins.AntigriefTowny; +import com.willfp.ecoenchants.integrations.antigrief.plugins.AntigriefWorldGuard; import com.willfp.ecoenchants.integrations.essentials.EssentialsManager; import com.willfp.ecoenchants.integrations.essentials.plugins.IntegrationEssentials; import com.willfp.ecoenchants.integrations.mcmmo.McmmoManager; @@ -40,6 +49,8 @@ import com.willfp.ecoenchants.integrations.worldguard.WorldguardManager; import com.willfp.ecoenchants.integrations.worldguard.plugins.WorldguardIntegrationImpl; import com.willfp.ecoenchants.util.interfaces.Callable; import com.willfp.ecoenchants.util.interfaces.EcoRunnable; +import com.willfp.ecoenchants.util.internal.drops.FastCollatedDropQueue; +import com.willfp.ecoenchants.util.internal.drops.InternalDropQueue; import com.willfp.ecoenchants.util.internal.updater.PlayerJoinListener; import com.willfp.ecoenchants.util.internal.updater.UpdateChecker; import com.willfp.ecoenchants.util.optional.Prerequisite; @@ -50,7 +61,11 @@ import org.bukkit.event.HandlerList; import org.bukkit.generator.BlockPopulator; import org.bukkit.plugin.Plugin; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Set; import java.util.stream.Collectors; /** @@ -367,7 +382,7 @@ public class Loader { EnchantmentRarity.update(); EnchantmentTarget.update(); EcoEnchants.update(); - DropQueue.update(); + InternalDropQueue.update(); EnchantDisplay.update(); TabCompleterEnchantinfo.reload(); FastCollatedDropQueue.update(); diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/AbstractDropQueue.java b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/AbstractDropQueue.java new file mode 100644 index 00000000..3a39e83b --- /dev/null +++ b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/AbstractDropQueue.java @@ -0,0 +1,66 @@ +package com.willfp.ecoenchants.util.internal.drops; + +import org.bukkit.Location; +import org.bukkit.inventory.ItemStack; + +import java.util.Collection; + +public interface AbstractDropQueue { + /** + * Add item to queue + * + * @param item The item to add + * + * @return The DropQueue + */ + AbstractDropQueue addItem(ItemStack item); + + /** + * Add multiple items to queue + * + * @param itemStacks The items to add + * + * @return The DropQueue + */ + AbstractDropQueue addItems(Collection itemStacks); + + /** + * Add xp to queue + * + * @param amount The amount to add + * + * @return The DropQueue + */ + AbstractDropQueue addXP(int amount); + + /** + * Set location of the origin of the drops + * + * @param l The location + * + * @return The DropQueue + */ + AbstractDropQueue setLocation(Location l); + + /** + * Force the queue to act as if player has {@link com.willfp.ecoenchants.enchantments.EcoEnchants#TELEKINESIS} + * + * @return The DropQueue + */ + AbstractDropQueue forceTelekinesis(); + + /** + * Set the queue to test specific item for {@link com.willfp.ecoenchants.enchantments.EcoEnchants#TELEKINESIS} + * Default item is the player's held item, however for this is required for Tridents. + * + * @param item The item to test + * + * @return The DropQueue + */ + AbstractDropQueue setItem(ItemStack item); + + /** + * Push the queue + */ + void push(); +} diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/FastCollatedDropQueue.java b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/FastCollatedDropQueue.java similarity index 67% rename from Plugin/src/main/java/com/willfp/ecoenchants/util/internal/FastCollatedDropQueue.java rename to Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/FastCollatedDropQueue.java index 97708658..cab570cb 100644 --- a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/FastCollatedDropQueue.java +++ b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/FastCollatedDropQueue.java @@ -1,45 +1,46 @@ -package com.willfp.ecoenchants.util.internal; +package com.willfp.ecoenchants.util.internal.drops; import com.willfp.ecoenchants.EcoEnchantsPlugin; import com.willfp.ecoenchants.config.ConfigManager; +import com.willfp.ecoenchants.util.internal.DropQueue; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -public class FastCollatedDropQueue { +/** + * Backend implementation of {@link AbstractDropQueue} + * {@link this#push()} adds to a map that creates a new {@link InternalDropQueue} at the end of every tick + * + * The drops are not instantly pushed when called, instead the map is iterated over at the end of every tick. This massively improves performance. + */ +public class FastCollatedDropQueue extends InternalDropQueue { private static boolean collate = false; private static final HashMap COLLATED_MAP = new HashMap<>(); - static { - Bukkit.getScheduler().runTaskTimer(EcoEnchantsPlugin.getInstance(), () -> { - if (!collate) return; - for (Map.Entry entry : COLLATED_MAP.entrySet()) { - new DropQueue(entry.getKey()) - .setLocation(entry.getValue().getLocation()) - .addItems(entry.getValue().getDrops()) - .addXP(entry.getValue().getXp()) - .push(); - } - COLLATED_MAP.clear(); - }, 0, 1); - update(); + /** + * Create {@link DropQueue} linked to player + * + * @param player The player + */ + public FastCollatedDropQueue(Player player) { + super(player); } - public static void collateDrop(Player player, Collection items, int xp, Location location) { + @Override + public void push() { CollatedDrops collatedDrops; if(COLLATED_MAP.containsKey(player)) { List dropSet = COLLATED_MAP.get(player).getDrops(); dropSet.addAll(items); - collatedDrops = new CollatedDrops(dropSet, location, xp); + collatedDrops = new FastCollatedDropQueue.CollatedDrops(dropSet, loc, xp); } else { - collatedDrops = new CollatedDrops(new ArrayList<>(items), location, xp); + collatedDrops = new FastCollatedDropQueue.CollatedDrops(new ArrayList<>(items), loc, xp); } COLLATED_MAP.put(player, collatedDrops); @@ -53,6 +54,22 @@ public class FastCollatedDropQueue { collate = ConfigManager.getConfig().getBool( "drops.collate"); } + static { + Bukkit.getScheduler().runTaskTimer(EcoEnchantsPlugin.getInstance(), () -> { + if (!collate) return; + for (Map.Entry entry : COLLATED_MAP.entrySet()) { + new InternalDropQueue(entry.getKey()) + .setLocation(entry.getValue().getLocation()) + .addItems(entry.getValue().getDrops()) + .addXP(entry.getValue().getXp()) + .push(); + } + COLLATED_MAP.clear(); + }, 0, 1); + + update(); + } + private static class CollatedDrops { private final List drops; private final Location location; diff --git a/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/InternalDropQueue.java b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/InternalDropQueue.java new file mode 100644 index 00000000..87a3004d --- /dev/null +++ b/Plugin/src/main/java/com/willfp/ecoenchants/util/internal/drops/InternalDropQueue.java @@ -0,0 +1,168 @@ +package com.willfp.ecoenchants.util.internal.drops; + +import com.willfp.ecoenchants.enchantments.EcoEnchants; +import com.willfp.ecoenchants.enchantments.util.EnchantChecks; +import com.willfp.ecoenchants.util.NumberUtils; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.World; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ExperienceOrb; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerExpChangeEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +public class InternalDropQueue implements AbstractDropQueue { + protected final List items; + protected int xp; + protected final Player player; + protected Location loc; + protected boolean hasTelekinesis = false; + protected ItemStack item; + + private static boolean useOrb; + + /** + * Create {@link com.willfp.ecoenchants.util.internal.DropQueue} linked to player + * + * @param player The player + */ + public InternalDropQueue(Player player) { + this.items = new ArrayList<>(); + this.xp = 0; + this.player = player; + this.loc = player.getLocation(); + this.item = player.getInventory().getItemInMainHand(); + } + + /** + * Add item to queue + * + * @param item The item to add + * + * @return The DropQueue + */ + @Override + public AbstractDropQueue addItem(ItemStack item) { + this.items.add(item); + return this; + } + + /** + * Add multiple items to queue + * + * @param itemStacks The items to add + * + * @return The DropQueue + */ + @Override + public AbstractDropQueue addItems(Collection itemStacks) { + this.items.addAll(itemStacks); + return this; + } + + /** + * Add xp to queue + * + * @param amount The amount to add + * + * @return The DropQueue + */ + @Override + public AbstractDropQueue addXP(int amount) { + this.xp += amount; + return this; + } + + /** + * Set location of the origin of the drops + * + * @param l The location + * + * @return The DropQueue + */ + @Override + public AbstractDropQueue setLocation(Location l) { + this.loc = l; + return this; + } + + /** + * Force the queue to act as if player has {@link EcoEnchants#TELEKINESIS} + * + * @return The DropQueue + */ + @Override + public AbstractDropQueue forceTelekinesis() { + this.hasTelekinesis = true; + return this; + } + + /** + * Set the queue to test specific item for {@link EcoEnchants#TELEKINESIS} + * Default item is the player's held item, however for this is required for Tridents. + * + * @param item The item to test + * + * @return The DropQueue + */ + @Override + public AbstractDropQueue setItem(ItemStack item) { + this.item = item; + return this; + } + + /** + * Push the queue + */ + public void push() { + if(!hasTelekinesis) hasTelekinesis = EnchantChecks.item(item, EcoEnchants.TELEKINESIS); + if(hasTelekinesis && !EcoEnchants.TELEKINESIS.isEnabled()) hasTelekinesis = false; + + World world = loc.getWorld(); + assert world != null; + + if(hasTelekinesis) { + HashMap leftover = player.getInventory().addItem(items.toArray(new ItemStack[]{})); + for(ItemStack drop : leftover.values()) { + world.dropItemNaturally(loc.add(0.5, 0, 0.5), drop).setVelocity(new Vector()); + } + if (xp > 0) { + PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, xp); + Bukkit.getPluginManager().callEvent(event); + if (useOrb) { + ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(player.getLocation().add(0, 0.2, 0), EntityType.EXPERIENCE_ORB); + orb.setVelocity(new Vector(0, 0, 0)); + orb.setExperience(event.getAmount()); + } else { + player.giveExp(event.getAmount()); + player.playSound(player.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.AMBIENT, 1f, (float) NumberUtils.randFloat(0.7, 1.2)); + } + } + } else { + for (ItemStack drop : items) { + world.dropItemNaturally(loc.add(0.5, 0, 0.5), drop).setVelocity(new Vector()); + } + if (xp > 0) { + ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(loc, EntityType.EXPERIENCE_ORB); + orb.setExperience(xp); + } + } + } + + public static void update() { + useOrb = EcoEnchants.TELEKINESIS.getConfig().getBool(EcoEnchants.CONFIG_LOCATION + "use-orb"); + } + + static { + update(); + } +}