Reworked FastCollatedDropQueue into cleaner system

This commit is contained in:
Auxilor 2020-12-18 14:35:03 +00:00
parent baebd9e904
commit eff46ed738
8 changed files with 308 additions and 106 deletions

View File

@ -5,8 +5,8 @@ import com.willfp.ecoenchants.command.AbstractCommand;
import com.willfp.ecoenchants.display.EnchantmentCache; import com.willfp.ecoenchants.display.EnchantmentCache;
import com.willfp.ecoenchants.enchantments.EcoEnchant; import com.willfp.ecoenchants.enchantments.EcoEnchant;
import com.willfp.ecoenchants.enchantments.EcoEnchants; 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.Logger;
import com.willfp.ecoenchants.util.internal.drops.FastCollatedDropQueue;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
@ -14,7 +14,11 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import java.lang.reflect.Field; 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; import java.util.stream.Collectors;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -4,7 +4,6 @@ import com.willfp.ecoenchants.enchantments.EcoEnchant;
import com.willfp.ecoenchants.enchantments.util.EnchantChecks; import com.willfp.ecoenchants.enchantments.util.EnchantChecks;
import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager; import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager;
import com.willfp.ecoenchants.util.internal.DropQueue; import com.willfp.ecoenchants.util.internal.DropQueue;
import com.willfp.ecoenchants.util.internal.FastCollatedDropQueue;
import com.willfp.ecoenchants.util.tuplets.Pair; import com.willfp.ecoenchants.util.tuplets.Pair;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
@ -98,11 +97,6 @@ public class InfernalTouch extends EcoEnchant {
event.getItems().clear(); event.getItems().clear();
if(FastCollatedDropQueue.use()) {
FastCollatedDropQueue.collateDrop(player, drops, experience.get(), block.getLocation());
return;
}
new DropQueue(player) new DropQueue(player)
.setLocation(block.getLocation()) .setLocation(block.getLocation())
.addItems(drops) .addItems(drops)

View File

@ -8,7 +8,6 @@ import com.willfp.ecoenchants.events.entitydeathbyentity.EntityDeathByEntityEven
import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager; import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager;
import com.willfp.ecoenchants.nms.TridentStack; import com.willfp.ecoenchants.nms.TridentStack;
import com.willfp.ecoenchants.util.internal.DropQueue; import com.willfp.ecoenchants.util.internal.DropQueue;
import com.willfp.ecoenchants.util.internal.FastCollatedDropQueue;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.block.Block; import org.bukkit.block.Block;
@ -56,11 +55,6 @@ public class Telekinesis extends EcoEnchant {
event.getItems().clear(); event.getItems().clear();
if(FastCollatedDropQueue.use()) {
FastCollatedDropQueue.collateDrop(player, drops, 0, block.getLocation());
return;
}
new DropQueue(player) new DropQueue(player)
.setLocation(block.getLocation()) .setLocation(block.getLocation())
.addItems(drops) .addItems(drops)

View File

@ -1,34 +1,21 @@
package com.willfp.ecoenchants.util.internal; package com.willfp.ecoenchants.util.internal;
import com.willfp.ecoenchants.enchantments.EcoEnchants; import com.willfp.ecoenchants.enchantments.EcoEnchants;
import com.willfp.ecoenchants.enchantments.util.EnchantChecks; import com.willfp.ecoenchants.util.internal.drops.AbstractDropQueue;
import com.willfp.ecoenchants.util.NumberUtils; import com.willfp.ecoenchants.util.internal.drops.FastCollatedDropQueue;
import org.bukkit.*; import com.willfp.ecoenchants.util.internal.drops.InternalDropQueue;
import org.bukkit.entity.EntityType; import org.bukkit.Location;
import org.bukkit.entity.ExperienceOrb;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List;
/** /**
* All drops generated from enchantments should be sent through a {@link DropQueue} * All drops generated from enchantments should be sent through a {@link DropQueue}
* Interacts with {@link EcoEnchants#TELEKINESIS} * Interacts with {@link EcoEnchants#TELEKINESIS}
*/ */
public class DropQueue { public class DropQueue {
private final List<ItemStack> items; private final AbstractDropQueue handle;
private int xp;
private final Player player;
private Location loc;
private boolean hasTelekinesis = false;
private ItemStack item;
private static boolean useOrb;
/** /**
* Create {@link DropQueue} linked to player * Create {@link DropQueue} linked to player
@ -36,11 +23,7 @@ public class DropQueue {
* @param player The player * @param player The player
*/ */
public DropQueue(Player player) { public DropQueue(Player player) {
this.items = new ArrayList<>(); handle = FastCollatedDropQueue.use() ? new FastCollatedDropQueue(player) : new InternalDropQueue(player);
this.xp = 0;
this.player = player;
this.loc = player.getLocation();
this.item = player.getInventory().getItemInMainHand();
} }
/** /**
@ -51,7 +34,7 @@ public class DropQueue {
* @return The DropQueue * @return The DropQueue
*/ */
public DropQueue addItem(ItemStack item) { public DropQueue addItem(ItemStack item) {
this.items.add(item); handle.addItem(item);
return this; return this;
} }
@ -63,7 +46,7 @@ public class DropQueue {
* @return The DropQueue * @return The DropQueue
*/ */
public DropQueue addItems(Collection<ItemStack> itemStacks) { public DropQueue addItems(Collection<ItemStack> itemStacks) {
this.items.addAll(itemStacks); handle.addItems(itemStacks);
return this; return this;
} }
@ -75,7 +58,7 @@ public class DropQueue {
* @return The DropQueue * @return The DropQueue
*/ */
public DropQueue addXP(int amount) { public DropQueue addXP(int amount) {
this.xp += amount; handle.addXP(amount);
return this; return this;
} }
@ -87,7 +70,7 @@ public class DropQueue {
* @return The DropQueue * @return The DropQueue
*/ */
public DropQueue setLocation(Location l) { public DropQueue setLocation(Location l) {
this.loc = l; handle.setLocation(l);
return this; return this;
} }
@ -97,7 +80,7 @@ public class DropQueue {
* @return The DropQueue * @return The DropQueue
*/ */
public DropQueue forceTelekinesis() { public DropQueue forceTelekinesis() {
this.hasTelekinesis = true; handle.forceTelekinesis();
return this; return this;
} }
@ -110,7 +93,7 @@ public class DropQueue {
* @return The DropQueue * @return The DropQueue
*/ */
public DropQueue setItem(ItemStack item) { public DropQueue setItem(ItemStack item) {
this.item = item; handle.setItem(item);
return this; return this;
} }
@ -118,45 +101,6 @@ public class DropQueue {
* Push the queue * Push the queue
*/ */
public void push() { public void push() {
if(!hasTelekinesis) hasTelekinesis = EnchantChecks.item(item, EcoEnchants.TELEKINESIS); handle.push();
if(hasTelekinesis && !EcoEnchants.TELEKINESIS.isEnabled()) hasTelekinesis = false;
World world = loc.getWorld();
assert world != null;
if(hasTelekinesis) {
HashMap<Integer, ItemStack> 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();
} }
} }

View File

@ -8,7 +8,11 @@ import com.willfp.ecoenchants.command.tabcompleters.TabCompleterEnchantinfo;
import com.willfp.ecoenchants.config.ConfigManager; import com.willfp.ecoenchants.config.ConfigManager;
import com.willfp.ecoenchants.display.EnchantDisplay; import com.willfp.ecoenchants.display.EnchantDisplay;
import com.willfp.ecoenchants.display.EnchantmentCache; 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.EcoEnchant;
import com.willfp.ecoenchants.enchantments.EcoEnchants; import com.willfp.ecoenchants.enchantments.EcoEnchants;
import com.willfp.ecoenchants.enchantments.meta.EnchantmentRarity; 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.AnticheatNCP;
import com.willfp.ecoenchants.integrations.anticheat.plugins.AnticheatSpartan; import com.willfp.ecoenchants.integrations.anticheat.plugins.AnticheatSpartan;
import com.willfp.ecoenchants.integrations.antigrief.AntigriefManager; 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.EssentialsManager;
import com.willfp.ecoenchants.integrations.essentials.plugins.IntegrationEssentials; import com.willfp.ecoenchants.integrations.essentials.plugins.IntegrationEssentials;
import com.willfp.ecoenchants.integrations.mcmmo.McmmoManager; 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.integrations.worldguard.plugins.WorldguardIntegrationImpl;
import com.willfp.ecoenchants.util.interfaces.Callable; import com.willfp.ecoenchants.util.interfaces.Callable;
import com.willfp.ecoenchants.util.interfaces.EcoRunnable; 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.PlayerJoinListener;
import com.willfp.ecoenchants.util.internal.updater.UpdateChecker; import com.willfp.ecoenchants.util.internal.updater.UpdateChecker;
import com.willfp.ecoenchants.util.optional.Prerequisite; import com.willfp.ecoenchants.util.optional.Prerequisite;
@ -50,7 +61,11 @@ import org.bukkit.event.HandlerList;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.plugin.Plugin; 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; import java.util.stream.Collectors;
/** /**
@ -367,7 +382,7 @@ public class Loader {
EnchantmentRarity.update(); EnchantmentRarity.update();
EnchantmentTarget.update(); EnchantmentTarget.update();
EcoEnchants.update(); EcoEnchants.update();
DropQueue.update(); InternalDropQueue.update();
EnchantDisplay.update(); EnchantDisplay.update();
TabCompleterEnchantinfo.reload(); TabCompleterEnchantinfo.reload();
FastCollatedDropQueue.update(); FastCollatedDropQueue.update();

View File

@ -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<ItemStack> 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();
}

View File

@ -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.EcoEnchantsPlugin;
import com.willfp.ecoenchants.config.ConfigManager; import com.willfp.ecoenchants.config.ConfigManager;
import com.willfp.ecoenchants.util.internal.DropQueue;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; 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 boolean collate = false;
private static final HashMap<Player, CollatedDrops> COLLATED_MAP = new HashMap<>(); private static final HashMap<Player, CollatedDrops> COLLATED_MAP = new HashMap<>();
static {
Bukkit.getScheduler().runTaskTimer(EcoEnchantsPlugin.getInstance(), () -> {
if (!collate) return;
for (Map.Entry<Player, CollatedDrops> 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<ItemStack> items, int xp, Location location) { @Override
public void push() {
CollatedDrops collatedDrops; CollatedDrops collatedDrops;
if(COLLATED_MAP.containsKey(player)) { if(COLLATED_MAP.containsKey(player)) {
List<ItemStack> dropSet = COLLATED_MAP.get(player).getDrops(); List<ItemStack> dropSet = COLLATED_MAP.get(player).getDrops();
dropSet.addAll(items); dropSet.addAll(items);
collatedDrops = new CollatedDrops(dropSet, location, xp); collatedDrops = new FastCollatedDropQueue.CollatedDrops(dropSet, loc, xp);
} else { } else {
collatedDrops = new CollatedDrops(new ArrayList<>(items), location, xp); collatedDrops = new FastCollatedDropQueue.CollatedDrops(new ArrayList<>(items), loc, xp);
} }
COLLATED_MAP.put(player, collatedDrops); COLLATED_MAP.put(player, collatedDrops);
@ -53,6 +54,22 @@ public class FastCollatedDropQueue {
collate = ConfigManager.getConfig().getBool( "drops.collate"); collate = ConfigManager.getConfig().getBool( "drops.collate");
} }
static {
Bukkit.getScheduler().runTaskTimer(EcoEnchantsPlugin.getInstance(), () -> {
if (!collate) return;
for (Map.Entry<Player, CollatedDrops> 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 static class CollatedDrops {
private final List<ItemStack> drops; private final List<ItemStack> drops;
private final Location location; private final Location location;

View File

@ -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<ItemStack> 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<ItemStack> 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<Integer, ItemStack> 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();
}
}