Reworked eco-util into it's own project

This commit is contained in:
Auxilor 2020-12-31 19:09:32 +00:00
parent 4b115b8334
commit 6f547f21dd
93 changed files with 6 additions and 5830 deletions

View File

@ -7,7 +7,7 @@ plugins {
dependencies {
implementation project(":eco-core").getSubprojects()
implementation project(":eco-util")
implementation 'com.willfp:eco:1.0.0'
}
allprojects {
@ -85,8 +85,9 @@ clean.doLast {
}
shadowJar {
relocate('org.bstats.bukkit', 'com.willfp.eco.util.shaded.bstats')
relocate('org.apache.maven', 'com.willfp.eco.util.shaded.maven')
relocate('org.apache', 'com.willfp.ecoenchants.eco.shaded.apache')
relocate('org.bstats', 'com.willfp.ecoenchants.eco.shaded.bstats')
relocate('com.willfp.eco.', 'com.willfp.ecoenchants.eco.') // Dot is to prevent plugin being shaded into itself
archiveFileName = findProperty("plugin-name") + " v" + findProperty("version") + ".jar"
}

View File

@ -3,6 +3,6 @@ version rootProject.version
subprojects {
dependencies {
compileOnly project(":eco-util")
compileOnly 'com.willfp:eco:1.0.0'
}
}

View File

@ -5,7 +5,7 @@ subprojects {
dependencies {
compileOnly project(":eco-core:core-plugin")
compileOnly project(":eco-core:core-proxy")
compileOnly project(":eco-util")
compileOnly 'com.willfp:eco:1.0.0'
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
}

View File

@ -1,23 +0,0 @@
group 'com.willfp'
version rootProject.version
repositories {
maven { url 'https://repo.dmulloy2.net/nexus/repository/public/' }
}
dependencies {
implementation 'org.apache.maven:maven-artifact:3.0.3'
implementation 'org.bstats:bstats-bukkit:1.7'
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT'
compileOnly 'me.clip:placeholderapi:2.10.9'
compileOnly 'com.comphenix.protocol:ProtocolLib:4.6.0-SNAPSHOT'
compileOnly 'com.sk89q.worldguard:worldguard-bukkit:7.0.4-SNAPSHOT'
compileOnly 'com.github.TechFortress:GriefPrevention:16.14.0'
compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
compileOnly 'com.github.cryptomorin:kingdoms:1.10.3.1'
compileOnly 'com.github.TownyAdvanced:Towny:0.96.2.0'
compileOnly 'com.github.angeschossen:LandsAPI:4.7.3'
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
compileOnly fileTree(dir: '/../lib', include: ['*.jar'])
}

View File

@ -1,47 +0,0 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@UtilityClass
public class BlockUtils {
private Set<Block> getNearbyBlocks(@NotNull final Block start,
@NotNull final List<Material> allowedMaterials,
@NotNull final HashSet<Block> blocks,
final int limit) {
for (BlockFace face : BlockFace.values()) {
Block block = start.getRelative(face);
if (!blocks.contains(block) && allowedMaterials.contains(block.getType())) {
blocks.add(block);
if (blocks.size() > limit || blocks.size() > 2500) {
return blocks;
}
blocks.addAll(getNearbyBlocks(block, allowedMaterials, blocks, limit));
}
}
return blocks;
}
/**
* Get a set of all blocks in contact with each other of a specific type.
*
* @param start The initial block.
* @param allowedMaterials A list of all valid {@link Material}s.
* @param limit The maximum size of vein to return.
*
* @return A set of all {@link Block}s.
*/
public Set<Block> getVein(@NotNull final Block start,
@NotNull final List<Material> allowedMaterials,
final int limit) {
return getNearbyBlocks(start, allowedMaterials, new HashSet<>(), limit);
}
}

View File

@ -1,23 +0,0 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class ClassUtils {
/**
* Get if a class exists.
*
* @param className The class to check.
* @return If the class exists.
* @see Class#forName(String)
*/
public boolean exists(@NotNull final String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}
}

View File

@ -1,124 +0,0 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerItemBreakEvent;
import org.bukkit.event.player.PlayerItemDamageEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;
import org.bukkit.inventory.meta.Damageable;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class DurabilityUtils {
/**
* Damage an item in a player's inventory.
* The slot of a held item can be obtained with {@link PlayerInventory#getHeldItemSlot()}.
* Armor slots are 39 (helmet), 38 (chestplate), 37 (leggings), 36 (boots).
*
* @param player The player.
* @param item The item to damage.
* @param damage The amount of damage to deal.
* @param slot The slot in the inventory of the item.
*/
public void damageItem(@NotNull final Player player,
@NotNull final ItemStack item,
final int damage,
final int slot) {
if (item.getItemMeta() == null) {
return;
}
if (item.getItemMeta().isUnbreakable()) {
return;
}
PlayerItemDamageEvent event3 = new PlayerItemDamageEvent(player, item, damage);
Bukkit.getPluginManager().callEvent(event3);
if (!event3.isCancelled()) {
int damage2 = event3.getDamage();
if (item.getItemMeta() instanceof Damageable) {
Damageable meta = (Damageable) item.getItemMeta();
meta.setDamage(meta.getDamage() + damage2);
if (meta.getDamage() >= item.getType().getMaxDurability()) {
meta.setDamage(item.getType().getMaxDurability());
item.setItemMeta((ItemMeta) meta);
PlayerItemBreakEvent event = new PlayerItemBreakEvent(player, item);
Bukkit.getPluginManager().callEvent(event);
player.getInventory().clear(slot);
player.playSound(player.getLocation(), Sound.ENTITY_ITEM_BREAK, SoundCategory.BLOCKS, 1, 1);
} else {
item.setItemMeta((ItemMeta) meta);
}
}
}
}
/**
* Damage an item in a player's inventory without breaking it.
*
* @param item The item to damage.
* @param damage The amount of damage to deal.
* @param player The player.
*/
public void damageItemNoBreak(@NotNull final ItemStack item,
final int damage,
@NotNull final Player player) {
if (item.getItemMeta() == null) {
return;
}
if (item.getItemMeta().isUnbreakable()) {
return;
}
PlayerItemDamageEvent event3 = new PlayerItemDamageEvent(player, item, damage);
Bukkit.getPluginManager().callEvent(event3);
if (!event3.isCancelled()) {
int damage2 = event3.getDamage();
if (item.getItemMeta() instanceof Damageable) {
Damageable meta = (Damageable) item.getItemMeta();
meta.setDamage(meta.getDamage() + damage2);
if (meta.getDamage() >= item.getType().getMaxDurability()) {
meta.setDamage(item.getType().getMaxDurability() - 1);
}
item.setItemMeta((ItemMeta) meta);
}
}
}
/**
* Repair an item in a player's inventory.
*
* @param item The item to damage.
* @param repair The amount of damage to heal.
*/
public void repairItem(@NotNull final ItemStack item,
final int repair) {
if (item.getItemMeta() == null) {
return;
}
if (item.getItemMeta().isUnbreakable()) {
return;
}
if (item.getItemMeta() instanceof Damageable) {
Damageable meta = (Damageable) item.getItemMeta();
meta.setDamage(meta.getDamage() - repair);
if (meta.getDamage() < 0) {
meta.setDamage(0);
}
item.setItemMeta((ItemMeta) meta);
}
}
}

View File

@ -1,24 +0,0 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class LightningUtils {
/**
* Strike lightning on player without fire.
*
* @param victim The entity to smite.
* @param damage The damage to deal.
*/
public void strike(@NotNull final LivingEntity victim,
final double damage) {
Location loc = victim.getLocation();
victim.getWorld().strikeLightningEffect(loc);
victim.damage(damage);
}
}

View File

@ -1,154 +0,0 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import java.text.DecimalFormat;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
@UtilityClass
public class NumberUtils {
/**
* Set of roman numerals to look up.
*/
private static final TreeMap<Integer, String> NUMERALS = new TreeMap<>();
static {
NUMERALS.put(1000, "M");
NUMERALS.put(900, "CM");
NUMERALS.put(500, "D");
NUMERALS.put(400, "CD");
NUMERALS.put(100, "C");
NUMERALS.put(90, "XC");
NUMERALS.put(50, "L");
NUMERALS.put(40, "XL");
NUMERALS.put(10, "X");
NUMERALS.put(9, "IX");
NUMERALS.put(5, "V");
NUMERALS.put(4, "IV");
NUMERALS.put(1, "I");
}
/**
* Bias the input value according to a curve.
*
* @param input The input value.
* @param bias The bias between -1 and 1, where higher values bias input values to lower output values.
* @return The biased output.
*/
public double bias(final double input,
final double bias) {
double k = Math.pow(1 - bias, 3);
return (input * k) / (input * k - input + 1);
}
/**
* If value is above maximum, set it to maximum.
*
* @param toChange The value to test.
* @param limit The maximum.
* @return The new value.
*/
public int equalIfOver(final int toChange,
final int limit) {
return Math.min(toChange, limit);
}
/**
* If value is above maximum, set it to maximum.
*
* @param toChange The value to test.
* @param limit The maximum.
* @return The new value.
*/
public double equalIfOver(final double toChange,
final double limit) {
return Math.min(toChange, limit);
}
/**
* Get Roman Numeral from number.
*
* @param number The number to convert.
* @return The number, converted to a roman numeral.
*/
public String toNumeral(final int number) {
if (number >= 1 && number <= 4096) {
int l = NUMERALS.floorKey(number);
if (number == l) {
return NUMERALS.get(number);
}
return NUMERALS.get(l) + toNumeral(number - l);
} else {
return String.valueOf(number);
}
}
/**
* Generate random integer in range.
*
* @param min Minimum.
* @param max Maximum.
* @return Random integer.
*/
public int randInt(final int min,
final int max) {
return ThreadLocalRandom.current().nextInt(min, max + 1);
}
/**
* Generate random double in range.
*
* @param min Minimum.
* @param max Maximum.
* @return Random double.
*/
public double randFloat(final double min,
final double max) {
return ThreadLocalRandom.current().nextDouble(min, max);
}
/**
* Generate random double with a triangular distribution.
*
* @param minimum Minimum.
* @param maximum Maximum.
* @param peak Peak.
* @return Random double.
*/
public double triangularDistribution(final double minimum,
final double maximum,
final double peak) {
double f = (peak - minimum) / (maximum - minimum);
double rand = Math.random();
if (rand < f) {
return minimum + Math.sqrt(rand * (maximum - minimum) * (peak - minimum));
} else {
return maximum - Math.sqrt((1 - rand) * (maximum - minimum) * (maximum - peak));
}
}
/**
* Get Log base 2 of a number.
*
* @param toLog The number.
* @return The result.
*/
public int log2(final int toLog) {
return (int) (Math.log(toLog) / Math.log(2));
}
/**
* Format double to string.
*
* @param toFormat The number to format.
* @return Formatted.
*/
public String format(final double toFormat) {
DecimalFormat df = new DecimalFormat("0.00");
String formatted = df.format(toFormat);
return formatted.endsWith("00") ? String.valueOf((int) toFormat) : formatted;
}
}

View File

@ -1,21 +0,0 @@
package com.willfp.eco.util;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import com.willfp.eco.util.proxy.AbstractProxy;
import com.willfp.eco.util.proxy.ProxyFactory;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.NotNull;
@UtilityClass
public class ProxyUtils {
/**
* Get the implementation of a specified proxy.
*
* @param proxyClass The proxy interface.
* @param <T> The type of the proxy.
* @return The proxy implementation.
*/
public @NotNull <T extends AbstractProxy> T getProxy(@NotNull final Class<T> proxyClass) {
return new ProxyFactory<>(AbstractEcoPlugin.getInstance(), proxyClass).getProxy();
}
}

View File

@ -1,105 +0,0 @@
package com.willfp.eco.util;
import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
import lombok.experimental.UtilityClass;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static net.md_5.bungee.api.ChatColor.COLOR_CHAR;
@UtilityClass
public class StringUtils {
/**
* Translate a string - converts Placeholders and Color codes.
*
* @param message The message to translate.
* @param player The player to translate placeholders with respect to.
* @return The message, translated.
*/
public String translate(@NotNull final String message,
@Nullable final Player player) {
String processedMessage = message;
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, player);
processedMessage = translateHexColorCodes(processedMessage);
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
return ChatColor.translateAlternateColorCodes('&', translateHexColorCodes(processedMessage));
}
/**
* Translate a string without respect to a player.
*
* @param message The message to translate.
* @return The message, translated.
* @see StringUtils#translate(String, Player)
*/
public String translate(@NotNull final String message) {
String processedMessage = message;
processedMessage = PlaceholderManager.translatePlaceholders(processedMessage, null);
processedMessage = translateHexColorCodes(processedMessage);
processedMessage = ChatColor.translateAlternateColorCodes('&', processedMessage);
return ChatColor.translateAlternateColorCodes('&', translateHexColorCodes(processedMessage));
}
private static String translateHexColorCodes(@NotNull final String message) {
Pattern hexPattern = Pattern.compile("&#" + "([A-Fa-f0-9]{6})" + "");
Matcher matcher = hexPattern.matcher(message);
StringBuffer buffer = new StringBuffer(message.length() + 4 * 8);
while (matcher.find()) {
String group = matcher.group(1);
matcher.appendReplacement(buffer, COLOR_CHAR + "x"
+ COLOR_CHAR + group.charAt(0) + COLOR_CHAR + group.charAt(1)
+ COLOR_CHAR + group.charAt(2) + COLOR_CHAR + group.charAt(3)
+ COLOR_CHAR + group.charAt(4) + COLOR_CHAR + group.charAt(5));
}
return matcher.appendTail(buffer).toString();
}
/**
* Internal implementation of {@link String#valueOf}.
* Formats collections and doubles better.
*
* @param object The object to convert to string.
* @return The object stringified.
*/
public String internalToString(@Nullable final Object object) {
if (object == null) {
return "null";
}
if (object instanceof Integer) {
return ((Integer) object).toString();
} else if (object instanceof String) {
return (String) object;
} else if (object instanceof Double) {
return NumberUtils.format((Double) object);
} else if (object instanceof Collection<?>) {
Collection<?> c = (Collection<?>) object;
return c.stream().map(StringUtils::internalToString).collect(Collectors.joining(", "));
} else {
return String.valueOf(object);
}
}
/**
* Remove a string of characters from the start of a string.
*
* @param string The string to remove the prefix from.
* @param prefix The substring to remove.
* @return The string with the prefix removed.
*/
public String removePrefix(@NotNull final String string,
@NotNull final String prefix) {
if (string.startsWith(prefix)) {
return string.substring(prefix.length());
}
return string;
}
}

View File

@ -1,88 +0,0 @@
package com.willfp.eco.util;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.willfp.eco.util.optional.Prerequisite;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.scoreboard.Team;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Collectors;
@UtilityClass
public class TeamUtils {
/**
* Ore ChatColors.
*/
private static final BiMap<Material, ChatColor> MATERIAL_COLORS = HashBiMap.create();
/**
* All chat color teams.
*/
private static final BiMap<ChatColor, Team> CHAT_COLOR_TEAMS = HashBiMap.create();
/**
* The server scoreboard.
*/
private static final Scoreboard SCOREBOARD = Bukkit.getScoreboardManager().getMainScoreboard();
/**
* Get team from {@link ChatColor}.
* <p>
* For {@link org.bukkit.potion.PotionEffectType#GLOWING}.
*
* @param color The color to find the team for.
* @return The team.
*/
public Team fromChatColor(@NotNull final ChatColor color) {
if (CHAT_COLOR_TEAMS.containsKey(color)) {
return CHAT_COLOR_TEAMS.get(color);
}
Team team;
if (!SCOREBOARD.getTeams().stream().map(Team::getName).collect(Collectors.toList()).contains("EE-" + color.name())) {
team = SCOREBOARD.registerNewTeam("EE-" + color.name());
} else {
team = SCOREBOARD.getTeam("EE-" + color.name());
}
assert team != null;
team.setColor(color);
CHAT_COLOR_TEAMS.forcePut(color, team);
return team;
}
/**
* Get team from material.
* <p>
* For {@link org.bukkit.potion.PotionEffectType#GLOWING}.
*
* @param material The material to find the team from.
* @return The team.
*/
public Team getMaterialColorTeam(@NotNull final Material material) {
return fromChatColor(MATERIAL_COLORS.getOrDefault(material, ChatColor.WHITE));
}
static {
for (ChatColor value : ChatColor.values()) {
fromChatColor(value);
}
MATERIAL_COLORS.forcePut(Material.COAL_ORE, ChatColor.BLACK);
MATERIAL_COLORS.forcePut(Material.IRON_ORE, ChatColor.GRAY);
MATERIAL_COLORS.forcePut(Material.GOLD_ORE, ChatColor.YELLOW);
MATERIAL_COLORS.forcePut(Material.LAPIS_ORE, ChatColor.BLUE);
MATERIAL_COLORS.forcePut(Material.REDSTONE_ORE, ChatColor.RED);
MATERIAL_COLORS.forcePut(Material.DIAMOND_ORE, ChatColor.AQUA);
if (Prerequisite.MINIMUM_1_16.isMet()) {
MATERIAL_COLORS.forcePut(Material.ANCIENT_DEBRIS, ChatColor.DARK_RED);
}
}
}

View File

@ -1,134 +0,0 @@
package com.willfp.eco.util;
import lombok.experimental.UtilityClass;
import org.bukkit.util.NumberConversions;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@UtilityClass
public class VectorUtils {
/**
* If vector has all components as finite.
*
* @param vector The vector to check.
* @return If the vector is finite.
*/
public boolean isFinite(@NotNull final Vector vector) {
try {
NumberConversions.checkFinite(vector.getX(), "x not finite");
NumberConversions.checkFinite(vector.getY(), "y not finite");
NumberConversions.checkFinite(vector.getZ(), "z not finite");
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
/**
* Only keep largest part of normalised vector.
* For example: -0.8, 0.01, -0.2 would become -1, 0, 0.
*
* @param vec The vector to simplify.
* @return The vector, simplified.
*/
public Vector simplifyVector(@NotNull final Vector vec) {
double x = Math.abs(vec.getX());
double y = Math.abs(vec.getY());
double z = Math.abs(vec.getZ());
double max = Math.max(x, Math.max(y, z));
if (x > 1 || z > 1) {
max = y;
}
if (max == x) {
if (vec.getX() < 0) {
return new Vector(-1, 0, 0);
}
return new Vector(1, 0, 0);
} else if (max == y) {
if (vec.getY() < 0) {
return new Vector(0, -1, 0);
}
return new Vector(0, 1, 0);
} else {
if (vec.getZ() < 0) {
return new Vector(0, 0, -1);
}
return new Vector(0, 0, 1);
}
}
/**
* Get circle as relative vectors.
*
* @param radius The radius.
* @return An array of {@link Vector}s.
*/
public Vector[] getCircle(final int radius) {
ArrayList<Vector> circleVecs = new ArrayList<>();
double xoffset = -radius;
double zoffset = -radius;
while (zoffset <= radius) {
while (xoffset <= radius) {
if (Math.round(Math.sqrt((xoffset * xoffset) + (zoffset * zoffset))) <= radius) {
circleVecs.add(new Vector(xoffset, 0, zoffset));
} else {
xoffset++;
continue;
}
xoffset++;
}
xoffset = -radius;
zoffset++;
}
return circleVecs.toArray(new Vector[0]);
}
/**
* Get square as relative vectors.
*
* @param radius The radius of the square.
* @return An array of {@link Vector}s.
*/
public Vector[] getSquare(final int radius) {
ArrayList<Vector> circleVecs = new ArrayList<>();
int xoffset = -radius;
int zoffset = -radius;
while (zoffset <= radius) {
while (xoffset <= radius) {
circleVecs.add(new Vector(xoffset, 0, zoffset));
xoffset++;
}
xoffset = -radius;
zoffset++;
}
return circleVecs.toArray(new Vector[0]);
}
/**
* Get cube as relative vectors.
*
* @param radius The radius of the cube.
* @return An array of {@link Vector}s.
*/
public Vector[] getCube(final int radius) {
ArrayList<Vector> cubeVecs = new ArrayList<>();
for (int y = -radius; y <= radius; y++) {
for (int z = -radius; z <= radius; z++) {
for (int x = -radius; x <= radius; x++) {
cubeVecs.add(new Vector(x, y, z));
}
}
}
return cubeVecs.toArray(new Vector[0]);
}
}

View File

@ -1,60 +0,0 @@
package com.willfp.eco.util.arrows;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ProjectileLaunchEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class ArrowDataListener extends PluginDependent implements Listener {
/**
* Listener to add metadata to arrows about the enchantments on the bow that shot them.
*
* @param plugin The {@link AbstractEcoPlugin} that registered the listener.
*/
@ApiStatus.Internal
public ArrowDataListener(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Listener for arrows being shot by entities.
*
* @param event The {@link ProjectileLaunchEvent} passed by spigot.
*/
@EventHandler(priority = EventPriority.LOWEST)
public void onLaunch(final ProjectileLaunchEvent event) {
if (!(event.getEntity() instanceof Arrow)) {
return;
}
if (!(event.getEntity().getShooter() instanceof LivingEntity)) {
return;
}
Arrow arrow = (Arrow) event.getEntity();
LivingEntity entity = (LivingEntity) arrow.getShooter();
if (entity.getEquipment() == null) {
return;
}
ItemStack item = entity.getEquipment().getItemInMainHand();
if (item.getType().equals(Material.AIR) || !item.hasItemMeta() || item.getItemMeta() == null) {
return;
}
Map<Enchantment, Integer> enchantments = item.getItemMeta().getEnchants();
arrow.setMetadata("enchantments", this.getPlugin().getMetadataValueFactory().create(enchantments));
}
}

View File

@ -1,51 +0,0 @@
package com.willfp.eco.util.bukkit.events;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
public class EcoEventManager extends PluginDependent implements EventManager {
/**
* Manager class for event management.
* <p>
* Prevents calls to {@link AbstractEcoPlugin#getInstance()}.
*
* @param plugin The {@link AbstractEcoPlugin} that this manages the events of.
*/
@ApiStatus.Internal
public EcoEventManager(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Register a listener with bukkit.
*
* @param listener The listener to register.
*/
@Override
public void registerListener(@NotNull final Listener listener) {
Bukkit.getPluginManager().registerEvents(listener, this.getPlugin());
}
/**
* Unregister a listener with bukkit.
*
* @param listener The listener to unregister.
*/
@Override
public void unregisterListener(@NotNull final Listener listener) {
HandlerList.unregisterAll(listener);
}
/**
* Unregister all listeners associated with the plugin.
*/
@Override
public void unregisterAllListeners() {
HandlerList.unregisterAll(this.getPlugin());
}
}

View File

@ -1,24 +0,0 @@
package com.willfp.eco.util.bukkit.events;
import org.bukkit.event.Listener;
public interface EventManager {
/**
* Register a listener with bukkit.
*
* @param listener The listener to register.
*/
void registerListener(Listener listener);
/**
* Unregister a listener with bukkit.
*
* @param listener The listener to unregister.
*/
void unregisterListener(Listener listener);
/**
* Unregister all listeners associated with the plugin.
*/
void unregisterAllListeners();
}

View File

@ -1,27 +0,0 @@
package com.willfp.eco.util.bukkit.keys;
import com.willfp.eco.util.internal.PluginDependentFactory;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.NamespacedKey;
import org.jetbrains.annotations.NotNull;
public class NamespacedKeyFactory extends PluginDependentFactory {
/**
* Factory class to produce {@link NamespacedKey}s associated with an {@link AbstractEcoPlugin}.
*
* @param plugin The plugin that this factory creates keys for.
*/
public NamespacedKeyFactory(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Create an {@link NamespacedKey} associated with an {@link AbstractEcoPlugin}.
*
* @param key The key in the {@link NamespacedKey}.
* @return The created {@link NamespacedKey}.
*/
public NamespacedKey create(@NotNull final String key) {
return new NamespacedKey(this.getPlugin(), key);
}
}

View File

@ -1,48 +0,0 @@
package com.willfp.eco.util.bukkit.logging;
import com.willfp.eco.util.StringUtils;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.jetbrains.annotations.NotNull;
public class EcoLogger extends PluginDependent implements Logger {
/**
* Implementation of {@link Logger}.
* Manages logging for an {@link AbstractEcoPlugin}.
*
* @param plugin The {@link AbstractEcoPlugin} for the logger to manage.
*/
public EcoLogger(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Log an informative/neutral message to console.
*
* @param message The message to log.
*/
@Override
public void info(@NotNull final String message) {
this.getPlugin().getLogger().info(StringUtils.translate(message));
}
/**
* Log a warning to console.
*
* @param message The message to log.
*/
@Override
public void warn(@NotNull final String message) {
this.getPlugin().getLogger().warning(StringUtils.translate(message));
}
/**
* Log an error to console.
*
* @param message The message to log.
*/
@Override
public void error(@NotNull final String message) {
this.getPlugin().getLogger().severe(StringUtils.translate(message));
}
}

View File

@ -1,24 +0,0 @@
package com.willfp.eco.util.bukkit.logging;
public interface Logger {
/**
* Log an informative/neutral message to console.
*
* @param message The message to log.
*/
void info(String message);
/**
* Log a warning to console.
*
* @param message The message to log.
*/
void warn(String message);
/**
* Log an error to console.
*
* @param message The message to log.
*/
void error(String message);
}

View File

@ -1,27 +0,0 @@
package com.willfp.eco.util.bukkit.meta;
import com.willfp.eco.util.internal.PluginDependentFactory;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.metadata.FixedMetadataValue;
import org.jetbrains.annotations.NotNull;
public class MetadataValueFactory extends PluginDependentFactory {
/**
* Factory class to produce {@link FixedMetadataValue}s associated with an {@link AbstractEcoPlugin}.
*
* @param plugin The plugin that this factory creates values for.
*/
public MetadataValueFactory(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Create an {@link FixedMetadataValue} associated with an {@link AbstractEcoPlugin} with a specified value.
*
* @param value The value of meta key.
* @return The created {@link FixedMetadataValue}.
*/
public FixedMetadataValue create(@NotNull final Object value) {
return new FixedMetadataValue(this.getPlugin(), value);
}
}

View File

@ -1,101 +0,0 @@
package com.willfp.eco.util.bukkit.scheduling;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
public abstract class EcoBukkitRunnable extends BukkitRunnable {
/**
* The linked {@link AbstractEcoPlugin} to associate runnables with.
*/
private final AbstractEcoPlugin plugin;
/**
* Creates a new {@link EcoBukkitRunnable}.
* <p>
* Cannot be instantiated normally, use {@link RunnableFactory}.
*
* @param plugin The {@link AbstractEcoPlugin} to associate runnables with.
*/
@ApiStatus.Internal
EcoBukkitRunnable(@NotNull final AbstractEcoPlugin plugin) {
this.plugin = plugin;
}
/**
* Get the {@link AbstractEcoPlugin} that created this runnable.
*
* @return The linked plugin.
*/
protected final AbstractEcoPlugin getPlugin() {
return this.plugin;
}
/**
* Run the task.
*
* @return The created {@link BukkitTask}.
*/
@NotNull
public final synchronized BukkitTask runTask() {
return super.runTask(plugin);
}
/**
* Run the task asynchronously.
*
* @return The created {@link BukkitTask}
*/
@NotNull
public final synchronized BukkitTask runTaskAsynchronously() {
return super.runTaskAsynchronously(plugin);
}
/**
* Run the task after a specified number of ticks.
*
* @param delay The number of ticks to wait.
* @return The created {@link BukkitTask}
*/
@NotNull
public final synchronized BukkitTask runTaskLater(final long delay) {
return super.runTaskLater(plugin, delay);
}
/**
* Run the task asynchronously after a specified number of ticks.
*
* @param delay The number of ticks to wait.
* @return The created {@link BukkitTask}
*/
@NotNull
public final synchronized BukkitTask runTaskLaterAsynchronously(final long delay) {
return super.runTaskLaterAsynchronously(plugin, delay);
}
/**
* Run the task repeatedly on a timer.
*
* @param delay The delay before the task is first ran (in ticks).
* @param period The ticks elapsed before the task is ran again.
* @return The created {@link BukkitTask}
*/
@NotNull
public final synchronized BukkitTask runTaskTimer(final long delay, final long period) {
return super.runTaskTimer(plugin, delay, period);
}
/**
* Run the task repeatedly on a timer asynchronously.
*
* @param delay The delay before the task is first ran (in ticks).
* @param period The ticks elapsed before the task is ran again.
* @return The created {@link BukkitTask}
*/
@NotNull
public final synchronized BukkitTask runTaskTimerAsynchronously(final long delay, final long period) {
return super.runTaskTimerAsynchronously(plugin, delay, period);
}
}

View File

@ -1,108 +0,0 @@
package com.willfp.eco.util.bukkit.scheduling;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Bukkit;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
public class EcoScheduler extends PluginDependent implements Scheduler {
/**
* Create a scheduler to manage the tasks of an {@link AbstractEcoPlugin}.
*
* @param plugin The plugin to manage.
*/
@ApiStatus.Internal
public EcoScheduler(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Run the task after a specified tick delay.
*
* @param runnable The lambda to run.
* @param ticksLater The amount of ticks to wait before execution.
* @return The created {@link BukkitTask}.
*/
@Override
public BukkitTask runLater(@NotNull final Runnable runnable,
final long ticksLater) {
return Bukkit.getScheduler().runTaskLater(this.getPlugin(), runnable, ticksLater);
}
/**
* Run the task repeatedly on a timer.
*
* @param runnable The lambda to run.
* @param delay The amount of ticks to wait before the first execution.
* @param repeat The amount of ticks to wait between executions.
* @return The created {@link BukkitTask}.
*/
@Override
public BukkitTask runTimer(@NotNull final Runnable runnable,
final long delay,
final long repeat) {
return Bukkit.getScheduler().runTaskTimer(this.getPlugin(), runnable, delay, repeat);
}
/**
* Run the task repeatedly and asynchronously on a timer.
*
* @param runnable The lambda to run.
* @param delay The amount of ticks to wait before the first execution.
* @param repeat The amount of ticks to wait between executions.
* @return The created {@link BukkitTask}.
*/
@Override
public BukkitTask runAsyncTimer(@NotNull final Runnable runnable,
final long delay,
final long repeat) {
return Bukkit.getScheduler().runTaskTimerAsynchronously(this.getPlugin(), runnable, delay, repeat);
}
/**
* Run the task.
*
* @param runnable The lambda to run.
* @return The created {@link BukkitTask}.
*/
@Override
public BukkitTask run(@NotNull final Runnable runnable) {
return Bukkit.getScheduler().runTask(this.getPlugin(), runnable);
}
/**
* Run the task asynchronously.
*
* @param runnable The lambda to run.
* @return The created {@link BukkitTask}.
*/
@Override
public BukkitTask runAsync(@NotNull final Runnable runnable) {
return Bukkit.getScheduler().runTaskAsynchronously(this.getPlugin(), runnable);
}
/**
* Schedule the task to be ran repeatedly on a timer.
*
* @param runnable The lambda to run.
* @param delay The amount of ticks to wait before the first execution.
* @param repeat The amount of ticks to wait between executions.
* @return The id of the task.
*/
@Override
public int syncRepeating(@NotNull final Runnable runnable,
final long delay,
final long repeat) {
return Bukkit.getScheduler().scheduleSyncRepeatingTask(this.getPlugin(), runnable, delay, repeat);
}
/**
* Cancel all running tasks from the linked {@link AbstractEcoPlugin}.
*/
@Override
public void cancelAll() {
Bukkit.getScheduler().cancelTasks(this.getPlugin());
}
}

View File

@ -1,33 +0,0 @@
package com.willfp.eco.util.bukkit.scheduling;
import com.willfp.eco.util.internal.PluginDependentFactory;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public class RunnableFactory extends PluginDependentFactory {
/**
* Factory class to produce {@link EcoBukkitRunnable}s associated with an {@link AbstractEcoPlugin}.
*
* @param plugin The plugin that this factory creates runnables for.
*/
public RunnableFactory(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Create an {@link EcoBukkitRunnable}.
*
* @param consumer Lambda of the code to run, where the parameter represents the instance of the runnable.
* @return The created {@link EcoBukkitRunnable}.
*/
public EcoBukkitRunnable create(@NotNull final Consumer<EcoBukkitRunnable> consumer) {
return new EcoBukkitRunnable(this.getPlugin()) {
@Override
public void run() {
consumer.accept(this);
}
};
}
}

View File

@ -1,67 +0,0 @@
package com.willfp.eco.util.bukkit.scheduling;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
public interface Scheduler {
/**
* Run the task after a specified tick delay.
*
* @param runnable The lambda to run.
* @param ticksLater The amount of ticks to wait before execution.
* @return The created {@link BukkitTask}.
*/
BukkitTask runLater(@NotNull Runnable runnable, long ticksLater);
/**
* Run the task repeatedly on a timer.
*
* @param runnable The lambda to run.
* @param delay The amount of ticks to wait before the first execution.
* @param repeat The amount of ticks to wait between executions.
* @return The created {@link BukkitTask}.
*/
BukkitTask runTimer(@NotNull Runnable runnable, long delay, long repeat);
/**
* Run the task repeatedly and asynchronously on a timer.
*
* @param runnable The lambda to run.
* @param delay The amount of ticks to wait before the first execution.
* @param repeat The amount of ticks to wait between executions.
* @return The created {@link BukkitTask}.
*/
BukkitTask runAsyncTimer(@NotNull Runnable runnable, long delay, long repeat);
/**
* Run the task.
*
* @param runnable The lambda to run.
* @return The created {@link BukkitTask}.
*/
BukkitTask run(@NotNull Runnable runnable);
/**
* Run the task asynchronously.
*
* @param runnable The lambda to run.
* @return The created {@link BukkitTask}.
*/
BukkitTask runAsync(@NotNull Runnable runnable);
/**
* Schedule the task to be ran repeatedly on a timer.
*
* @param runnable The lambda to run.
* @param delay The amount of ticks to wait before the first execution.
* @param repeat The amount of ticks to wait between executions.
* @return The id of the task.
*/
int syncRepeating(@NotNull Runnable runnable, long delay, long repeat);
/**
* Cancel all running tasks from the linked {@link AbstractEcoPlugin}.
*/
void cancelAll();
}

View File

@ -1,157 +0,0 @@
package com.willfp.eco.util.command;
import com.willfp.eco.util.config.Configs;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.interfaces.Registerable;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
public abstract class AbstractCommand extends PluginDependent implements CommandExecutor, Registerable {
/**
* The name of the command
* <p>
* i.e. the name used on execution, for example /enchantinfo would have the name enchantinfo.
*/
private final String name;
/**
* The permission required to execute the command.
* <p>
* Written out as a string for flexibility with subclasses.
*/
private final String permission;
/**
* Should the command only be allowed to be executed by players?
* <p>
* In other worlds, only allowed to be executed by console.
*/
private final boolean playersOnly;
/**
* Create a new command.
* <p>
* The command will not be registered until {@link this#register()} is called.
* <p>
* The name cannot be the same as an existing command as this will conflict.
*
* @param plugin The owning {@link AbstractEcoPlugin}.
* @param name The name used in execution.
* @param permission The permission required to execute the command.
* @param playersOnly If only players should be able to execute this command.
*/
protected AbstractCommand(@NotNull final AbstractEcoPlugin plugin,
@NotNull final String name,
@NotNull final String permission,
final boolean playersOnly) {
super(plugin);
this.name = name;
this.permission = permission;
this.playersOnly = playersOnly;
}
/**
* Get the {@link AbstractTabCompleter} associated with this command.
* <p>
* Implementations of {@link AbstractCommand} do not have to override this method:
* null represents no associated tab-completer.
*
* @return The associated {@link AbstractTabCompleter}, or null if none associated.
*/
public @Nullable AbstractTabCompleter getTab() {
return null;
}
/**
* Get the name of the permission required to execute this command.
*
* @return The name of the permission.
*/
public String getPermission() {
return this.permission;
}
/**
* Get the name of the command used in execution.
*
* @return The command name.
*/
public String getName() {
return this.name;
}
/**
* Internal implementation used to clean up boilerplate.
* Used for parity with {@link CommandExecutor#onCommand(CommandSender, Command, String, String[])}.
* <p>
* Calls {@link this#onExecute(CommandSender, List)}.
*
* @param sender The executor of the command.
* @param command The bukkit command.
* @param label The name of the executed command.
* @param args The arguments of the command (anything after the physical command name)
* @return If the command was processed by the linked {@link AbstractEcoPlugin}
*/
@Override
public final boolean onCommand(@NotNull final CommandSender sender,
@NotNull final Command command,
@NotNull final String label,
@NotNull final String[] args) {
if (!command.getName().equalsIgnoreCase(name)) {
return false;
}
if (playersOnly && !(sender instanceof Player)) {
sender.sendMessage(Configs.LANG.getMessage("not-player"));
return true;
}
if (!sender.hasPermission(permission) && sender instanceof Player) {
sender.sendMessage(Configs.LANG.getNoPermission());
return true;
}
onExecute(sender, Arrays.asList(args));
return true;
}
/**
* Registers the command with the server,
* <p>
* Requires the command name to exist, defined in plugin.yml.
*/
@Override
public final void register() {
PluginCommand command = Bukkit.getPluginCommand(name);
assert command != null;
command.setExecutor(this);
AbstractTabCompleter tabCompleter = this.getTab();
if (tabCompleter != null) {
command.setTabCompleter(tabCompleter);
}
}
/**
* The code for the execution of the command (The actual functionality).
* <p>
* Unlike {@link this#onCommand(CommandSender, Command, String, String[])},
* this does not return a value as the command <b>will</b> have been processed.
*
* @param sender The sender of the command
* @param args The arguments of the command
*/
protected abstract void onExecute(CommandSender sender,
List<String> args);
}

View File

@ -1,65 +0,0 @@
package com.willfp.eco.util.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
public abstract class AbstractTabCompleter implements TabCompleter {
/**
* The {@link AbstractCommand} that is tab-completed.
*/
private final AbstractCommand command;
/**
* Create a tab-completer for a specified {@link AbstractCommand}.
*
* @param command The command to tab-complete.
*/
protected AbstractTabCompleter(@NotNull final AbstractCommand command) {
this.command = command;
}
/**
* Internal implementation used to clean up boilerplate.
* Used for parity with {@link TabCompleter#onTabComplete(CommandSender, Command, String, String[])}.
* <p>
* Calls {@link this#onTab(CommandSender, List)}.
*
* @param sender The executor of the command.
* @param command The bukkit command.
* @param label The name of the executed command.
* @param args The arguments of the command (anything after the physical command name).
* @return The list of tab-completions.
*/
@Override
public @Nullable List<String> onTabComplete(@NotNull final CommandSender sender,
@NotNull final Command command,
@NotNull final String label,
@NotNull final String[] args) {
if (!command.getName().equalsIgnoreCase(this.command.getName())) {
return null;
}
if (!sender.hasPermission(this.command.getPermission())) {
return null;
}
return onTab(sender, Arrays.asList(args));
}
/**
* The code for the tab-completion of the command (The actual functionality).
* <p>
*
* @param sender The sender of the command.
* @param args The arguments of the command.
* @return The list of tab-completions.
*/
public abstract List<String> onTab(@NotNull CommandSender sender,
@NotNull List<String> args);
}

View File

@ -1,218 +0,0 @@
package com.willfp.eco.util.config;
import com.willfp.eco.util.StringUtils;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
public abstract class BaseConfig extends PluginDependent implements ValueGetter {
/**
* The linked {@link YamlConfiguration} where values are physically stored.
*/
@Getter(AccessLevel.PUBLIC)
private final YamlConfiguration config;
/**
* The physical config file, as stored on disk.
*/
private final File configFile;
/**
* The full name of the config file (eg config.yml).
*/
private final String name;
/**
* Whether keys not in the base config should be removed on update.
*/
private final boolean removeUnused;
/**
* Config implementation for configs present in the plugin's base directory (eg config.yml, lang.yml).
* <p>
* Automatically updates.
*
* @param configName The name of the config
* @param removeUnused Whether keys not present in the default config should be removed on update.
*/
protected BaseConfig(@NotNull final String configName,
final boolean removeUnused) {
super(AbstractEcoPlugin.getInstance());
this.name = configName + ".yml";
this.removeUnused = removeUnused;
if (!new File(this.getPlugin().getDataFolder(), this.name).exists()) {
createFile();
}
this.configFile = new File(this.getPlugin().getDataFolder(), this.name);
this.config = YamlConfiguration.loadConfiguration(configFile);
update();
}
private void createFile() {
this.getPlugin().saveResource(name, false);
}
/**
* Update the config.
* <p>
* Writes missing values, however removes comments due to how configs are stored internally in bukkit.
*/
public void update() {
try {
config.load(configFile);
InputStream newIn = this.getPlugin().getResource(name);
if (newIn == null) {
this.getPlugin().getLog().error(name + " is null?");
return;
}
BufferedReader reader = new BufferedReader(new InputStreamReader(newIn, StandardCharsets.UTF_8));
YamlConfiguration newConfig = new YamlConfiguration();
newConfig.load(reader);
if (newConfig.getKeys(true).equals(config.getKeys(true))) {
return;
}
newConfig.getKeys(true).forEach((s -> {
if (!config.getKeys(true).contains(s)) {
config.set(s, newConfig.get(s));
}
}));
if (this.removeUnused) {
config.getKeys(true).forEach((s -> {
if (!newConfig.getKeys(true).contains(s)) {
config.set(s, null);
}
}));
}
config.save(configFile);
} catch (IOException | InvalidConfigurationException e) {
e.printStackTrace();
}
}
/**
* Get an integer from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
@Override
public int getInt(@NotNull final String path) {
return config.getInt(path, 0);
}
/**
* Get an integer from config with a specified default (not found) value.
*
* @param path The key to fetch the value from.
* @param def The value to default to if not found.
* @return The found value, or the default.
*/
@Override
public int getInt(@NotNull final String path,
final int def) {
return config.getInt(path, def);
}
/**
* Get a list of integers from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<Integer> getInts(@NotNull final String path) {
return config.getIntegerList(path);
}
/**
* Get a boolean from config.
*
* @param path The key to fetch the value from.
* @return The found value, or false if not found.
*/
@Override
public boolean getBool(@NotNull final String path) {
return config.getBoolean(path, false);
}
/**
* Get a list of booleans from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<Boolean> getBools(@NotNull final String path) {
return config.getBooleanList(path);
}
/**
* Get a string from config.
*
* @param path The key to fetch the value from.
* @return The found value, or an empty string if not found.
*/
@Override
@NotNull
public String getString(@NotNull final String path) {
return StringUtils.translate(Objects.requireNonNull(config.getString(path, "")));
}
/**
* Get a list of strings from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<String> getStrings(@NotNull final String path) {
return config.getStringList(path);
}
/**
* Get a decimal from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
@Override
public double getDouble(@NotNull final String path) {
return config.getDouble(path, 0);
}
/**
* Get a list of decimals from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@Override
@NotNull
public List<Double> getDoubles(@NotNull final String path) {
return config.getDoubleList(path);
}
}

View File

@ -1,30 +0,0 @@
package com.willfp.eco.util.config;
import com.willfp.eco.util.config.updating.annotations.ConfigUpdater;
import com.willfp.eco.util.config.configs.Config;
import com.willfp.eco.util.config.configs.Lang;
import lombok.experimental.UtilityClass;
@UtilityClass
public final class Configs {
/**
* The {@link BaseConfig} implementation for lang.yml.
*/
public static final Lang LANG = new Lang();
/**
* The {@link BaseConfig} implementation for config.yml.
*/
public static final Config CONFIG = new Config();
/**
* Update lang.yml and config.yml.
*
* @see BaseConfig
*/
@ConfigUpdater
public void update() {
LANG.update();
CONFIG.update();
}
}

View File

@ -1,87 +0,0 @@
package com.willfp.eco.util.config;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@SuppressWarnings("unused")
public interface ValueGetter {
/**
* Get an integer from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
int getInt(@NotNull String path);
/**
* Get an integer from config with a specified default (not found) value.
*
* @param path The key to fetch the value from.
* @param def The value to default to if not found.
* @return The found value, or the default.
*/
int getInt(@NotNull String path,
int def);
/**
* Get a list of integers from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
List<Integer> getInts(@NotNull String path);
/**
* Get a boolean from config.
*
* @param path The key to fetch the value from.
* @return The found value, or false if not found.
*/
boolean getBool(@NotNull String path);
/**
* Get a list of booleans from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
List<Boolean> getBools(@NotNull String path);
/**
* Get a string from config.
*
* @param path The key to fetch the value from.
* @return The found value, or an empty string if not found.
*/
@NotNull
String getString(@NotNull String path);
/**
* Get a list of strings from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
List<String> getStrings(@NotNull String path);
/**
* Get a decimal from config.
*
* @param path The key to fetch the value from.
* @return The found value, or 0 if not found.
*/
double getDouble(@NotNull String path);
/**
* Get a list of decimals from config.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
List<Double> getDoubles(@NotNull String path);
}

View File

@ -1,13 +0,0 @@
package com.willfp.eco.util.config.configs;
import com.willfp.eco.util.config.BaseConfig;
public class Config extends BaseConfig {
/**
* Config.yml.
*/
public Config() {
super("config", true);
}
}

View File

@ -1,42 +0,0 @@
package com.willfp.eco.util.config.configs;
import com.willfp.eco.util.StringUtils;
import com.willfp.eco.util.config.BaseConfig;
import org.jetbrains.annotations.NotNull;
public class Lang extends BaseConfig {
/**
* lang.yml.
*/
public Lang() {
super("lang", false);
}
/**
* Get the prefix for messages in chat.
*
* @return The prefix.
*/
public String getPrefix() {
return StringUtils.translate(this.getConfig().getString("messages.prefix"));
}
/**
* Get the no permission message.
*
* @return The message.
*/
public String getNoPermission() {
return getPrefix() + StringUtils.translate(this.getConfig().getString("messages.no-permission"));
}
/**
* Get a chat message.
*
* @param message The key of the message.
* @return The message with a prefix appended.
*/
public String getMessage(@NotNull final String message) {
return getPrefix() + StringUtils.translate(this.getConfig().getString("messages." + message));
}
}

View File

@ -1,75 +0,0 @@
package com.willfp.eco.util.config.updating;
import com.willfp.eco.util.config.updating.annotations.ConfigUpdater;
import com.willfp.eco.util.config.updating.exceptions.InvalidUpdatableClassException;
import com.willfp.eco.util.config.updating.exceptions.InvalidUpdateMethodException;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class ConfigHandler extends PluginDependent {
/**
* A set of all classes that can be updated.
*/
private final Set<Class<?>> updatableClasses = new HashSet<>();
/**
* Creates a new config handler and links it to an {@link AbstractEcoPlugin}.
*
* @param plugin The plugin to manage.
*/
public ConfigHandler(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Invoke all update methods.
*/
public void callUpdate() {
updatableClasses.forEach(clazz -> Arrays.stream(clazz.getDeclaredMethods()).forEach(method -> {
if (method.isAnnotationPresent(ConfigUpdater.class)) {
if (method.getParameterTypes().length != 0) {
throw new InvalidUpdateMethodException("Update method must not have parameters.");
}
if (!Modifier.isStatic(method.getModifiers())) {
throw new InvalidUpdateMethodException("Update method must be static.");
}
try {
method.invoke(null);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
throw new InvalidUpdateMethodException("Update method generated an exception.");
}
}
}));
}
/**
* Register an updatable class.
*
* @param updatableClass The class with an update method.
*/
public void registerUpdatableClass(@NotNull final Class<?> updatableClass) {
boolean isValid = false;
for (Method method : updatableClass.getDeclaredMethods()) {
if (Modifier.isStatic(method.getModifiers()) && method.getParameterTypes().length == 0 && method.isAnnotationPresent(ConfigUpdater.class)) {
isValid = true;
break;
}
}
if (!isValid) {
throw new InvalidUpdatableClassException("Registered updatable class " + updatableClass + " must have an annotated static method with no modifiers.");
}
updatableClasses.add(updatableClass);
}
}

View File

@ -1,11 +0,0 @@
package com.willfp.eco.util.config.updating.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ConfigUpdater {
}

View File

@ -1,15 +0,0 @@
package com.willfp.eco.util.config.updating.exceptions;
import com.willfp.eco.util.config.updating.ConfigHandler;
import org.jetbrains.annotations.NotNull;
public class InvalidUpdatableClassException extends RuntimeException {
/**
* Called when an updatable class is registered into an {@link ConfigHandler}.
*
* @param message The error message.
*/
public InvalidUpdatableClassException(@NotNull final String message) {
super(message);
}
}

View File

@ -1,18 +0,0 @@
package com.willfp.eco.util.config.updating.exceptions;
import org.jetbrains.annotations.NotNull;
public class InvalidUpdateMethodException extends RuntimeException {
/**
* Throws a new invalid update method exception.
* <p>
* Causes include:
* Update method with parameters.
* Update method is not static.
*
* @param message The error message to show.
*/
public InvalidUpdateMethodException(@NotNull final String message) {
super(message);
}
}

View File

@ -1,92 +0,0 @@
package com.willfp.eco.util.drops;
import com.willfp.eco.util.drops.internal.AbstractDropQueue;
import com.willfp.eco.util.drops.internal.DropManager;
import com.willfp.eco.util.drops.internal.DropQueueType;
import com.willfp.eco.util.drops.internal.FastCollatedDropQueue;
import com.willfp.eco.util.drops.internal.InternalDropQueue;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public class DropQueue {
/**
* The internally used {@link AbstractDropQueue}.
*/
private final AbstractDropQueue handle;
/**
* Create {@link DropQueue} linked to player.
* <p>
* All drops should be passed through a drop queue for telekinesis integration.
*
* @param player The player.
*/
public DropQueue(@NotNull final Player player) {
handle = DropManager.getType() == DropQueueType.COLLATED ? new FastCollatedDropQueue(player) : new InternalDropQueue(player);
}
/**
* Add item to queue.
*
* @param item The item to add.
* @return The DropQueue.
*/
public DropQueue addItem(@NotNull final ItemStack item) {
handle.addItem(item);
return this;
}
/**
* Add multiple items to queue.
*
* @param itemStacks The items to add.
* @return The DropQueue.
*/
public DropQueue addItems(@NotNull final Collection<ItemStack> itemStacks) {
handle.addItems(itemStacks);
return this;
}
/**
* Add xp to queue.
*
* @param amount The amount to add.
* @return The DropQueue.
*/
public DropQueue addXP(final int amount) {
handle.addXP(amount);
return this;
}
/**
* Set location of the origin of the drops.
*
* @param location The location.
* @return The DropQueue.
*/
public DropQueue setLocation(@NotNull final Location location) {
handle.setLocation(location);
return this;
}
/**
* Force the queue to act as if player is telekinetic.
*
* @return The DropQueue.
*/
public DropQueue forceTelekinesis() {
handle.forceTelekinesis();
return this;
}
/**
* Push the queue.
*/
public void push() {
handle.push();
}
}

View File

@ -1,53 +0,0 @@
package com.willfp.eco.util.drops.internal;
import org.bukkit.Location;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
public interface AbstractDropQueue {
/**
* Add item to queue.
*
* @param item The item to add.
* @return The DropQueue.
*/
AbstractDropQueue addItem(@NotNull ItemStack item);
/**
* Add multiple items to queue.
*
* @param itemStacks The items to add.
* @return The DropQueue.
*/
AbstractDropQueue addItems(@NotNull 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 location The location.
* @return The DropQueue.
*/
AbstractDropQueue setLocation(@NotNull Location location);
/**
* Force the queue to act as if player is telekinetic.
*
* @return The DropQueue.
*/
AbstractDropQueue forceTelekinesis();
/**
* Push the queue.
*/
void push();
}

View File

@ -1,27 +0,0 @@
package com.willfp.eco.util.drops.internal;
import com.willfp.eco.util.config.Configs;
import com.willfp.eco.util.config.updating.annotations.ConfigUpdater;
import lombok.Getter;
import lombok.experimental.UtilityClass;
@UtilityClass
public final class DropManager {
/**
* The currently used type, or implementation, of {@link AbstractDropQueue}.
* <p>
* Standard by default, used if drops.collate key is not present in config.
*/
@Getter
private DropQueueType type = DropQueueType.STANDARD;
/**
* Update the type of drop queue that should be used.
*
* @see DropQueueType
*/
@ConfigUpdater
public void update() {
type = Configs.CONFIG.getBool("drops.collate") ? DropQueueType.COLLATED : DropQueueType.STANDARD;
}
}

View File

@ -1,15 +0,0 @@
package com.willfp.eco.util.drops.internal;
public enum DropQueueType {
/**
* As drops are processed, push them to the world or to the player's inventory.
*/
STANDARD,
/**
* As drops are processed, add them to a queue that are all collectively pushed at the end of a tick.
* <p>
* Generally better performance.
*/
COLLATED
}

View File

@ -1,134 +0,0 @@
package com.willfp.eco.util.drops.internal;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FastCollatedDropQueue extends InternalDropQueue {
/**
* The {@link CollatedDrops} linked to every player.
* <p>
* Cleared and updated every tick.
*/
private static final HashMap<Player, CollatedDrops> COLLATED_MAP = new HashMap<>();
/**
* Backend implementation of {@link AbstractDropQueue}
* {@link this#push()} adds to a map that creates a new {@link InternalDropQueue} at the end of every tick
* <p>
* The drops are not instantly pushed when called, instead the map is iterated over at the end of every tick. This massively improves performance.
*
* @param player The player to link the queue with.
*/
public FastCollatedDropQueue(@NotNull final Player player) {
super(player);
}
/**
* Queues the drops to be managed by the {@link CollatedRunnable}.
*/
@Override
public void push() {
CollatedDrops fetched = COLLATED_MAP.get(getPlayer());
CollatedDrops collatedDrops = fetched == null ? new CollatedDrops(getItems(), getLoc(), getXp()) : fetched.addDrops(getItems()).setLocation(getLoc()).addXp(getXp());
COLLATED_MAP.put(this.getPlayer(), collatedDrops);
}
/**
* The items, location, and xp linked to a player's drops.
*/
@ToString
private static final class CollatedDrops {
/**
* A collection of all ItemStacks to be dropped at the end of the tick.
*/
@Getter
private final List<ItemStack> drops;
/**
* The location to drop the items at.
*/
@Getter
@Setter
@Accessors(chain = true)
private Location location;
/**
* The xp to give to the player.
*/
@Getter
private int xp;
private CollatedDrops(@NotNull final List<ItemStack> drops,
@NotNull final Location location,
final int xp) {
this.drops = drops;
this.location = location;
this.xp = xp;
}
/**
* Add {@link ItemStack}s to the queue.
*
* @param toAdd The items to add.
* @return The instance of the {@link CollatedDrops}.
*/
public CollatedDrops addDrops(@NotNull final List<ItemStack> toAdd) {
drops.addAll(toAdd);
return this;
}
/**
* Add xp to the queue.
*
* @param xp The amount of xp to add.
* @return The instance of the {@link CollatedDrops}.
*/
public CollatedDrops addXp(final int xp) {
this.xp += xp;
return this;
}
}
public static class CollatedRunnable extends PluginDependent {
/**
* The {@link BukkitTask} that the runnable represents.
*/
@Getter
private final BukkitTask runnableTask;
/**
* Create and run a new runnable to process collated drops.
*
* @param plugin The {@link AbstractEcoPlugin} that manages the processing.
*/
@ApiStatus.Internal
public CollatedRunnable(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
runnableTask = plugin.getScheduler().runTimer(() -> {
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);
}
}
}

View File

@ -1,158 +0,0 @@
package com.willfp.eco.util.drops.internal;
import com.willfp.eco.util.drops.telekinesis.TelekinesisUtils;
import lombok.AccessLevel;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Location;
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 org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
public class InternalDropQueue implements AbstractDropQueue {
/**
* The items that the DropQueue stores.
*/
@Getter(AccessLevel.PROTECTED)
private final List<ItemStack> items;
/**
* The experience to give.
*/
@Getter(AccessLevel.PROTECTED)
private int xp;
/**
* The owner of the queue.
*/
@Getter(AccessLevel.PROTECTED)
private final Player player;
/**
* The location to drop the items and xp.
*/
@Getter(AccessLevel.PROTECTED)
private Location loc;
/**
* If the queue should be processed telekinetically.
*/
@Getter(AccessLevel.PROTECTED)
private boolean hasTelekinesis = false;
/**
* Create a DropQueue linked to player.
*
* @param player The player.
*/
public InternalDropQueue(@NotNull final Player player) {
this.items = new ArrayList<>();
this.xp = 0;
this.player = player;
this.loc = player.getLocation();
}
/**
* Add item to queue.
*
* @param item The item to add.
* @return The DropQueue.
*/
@Override
public AbstractDropQueue addItem(@NotNull final 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(@NotNull final 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(final int amount) {
this.xp += amount;
return this;
}
/**
* Set location of the origin of the drops.
*
* @param location The location.
* @return The DropQueue.
*/
@Override
public AbstractDropQueue setLocation(@NotNull final Location location) {
this.loc = location;
return this;
}
/**
* Force the queue to act as if player has a telekinetic item.
*
* @return The DropQueue.
*/
@Override
public AbstractDropQueue forceTelekinesis() {
this.hasTelekinesis = true;
return this;
}
/**
* Push the queue.
*/
public void push() {
if (!hasTelekinesis) {
hasTelekinesis = TelekinesisUtils.testPlayer(player);
}
World world = loc.getWorld();
assert world != null;
loc = loc.add(0.5, 0.5, 0.5);
if (hasTelekinesis) {
HashMap<Integer, ItemStack> leftover = player.getInventory().addItem(items.toArray(new ItemStack[0]));
for (ItemStack drop : leftover.values()) {
world.dropItem(loc, drop).setVelocity(new Vector());
}
if (xp > 0) {
PlayerExpChangeEvent event = new PlayerExpChangeEvent(player, xp);
Bukkit.getPluginManager().callEvent(event);
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 {
for (ItemStack drop : items) {
world.dropItem(loc, drop).setVelocity(new Vector());
}
if (xp > 0) {
ExperienceOrb orb = (ExperienceOrb) world.spawnEntity(loc, EntityType.EXPERIENCE_ORB);
orb.setExperience(xp);
}
}
}
}

View File

@ -1,44 +0,0 @@
package com.willfp.eco.util.drops.telekinesis;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Function;
public class EcoTelekinesisTests implements TelekinesisTests {
/**
* Set of tests that return if the player is telekinetic.
*/
private final Set<Function<Player, Boolean>> tests = new HashSet<>();
/**
* Register a new test to check against.
*
* @param test The test to register, where the boolean output is if the player is telekinetic.
*/
@Override
public void registerTest(@NotNull final Function<Player, Boolean> test) {
tests.add(test);
}
/**
* Test the player for telekinesis.
* <p>
* If any test returns true, so does this.
*
* @param player The player to test.
* @return If the player is telekinetic.
*/
@Override
public boolean testPlayer(@NotNull final Player player) {
for (Function<Player, Boolean> test : tests) {
if (test.apply(player)) {
return true;
}
}
return false;
}
}

View File

@ -1,23 +0,0 @@
package com.willfp.eco.util.drops.telekinesis;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
public interface TelekinesisTests {
/**
* Register a new test to check against.
*
* @param test The test to register, where the boolean output is if the player is telekinetic.
*/
void registerTest(@NotNull Function<Player, Boolean> test);
/**
* Test the player for telekinesis.
*
* @param player The player to test.
* @return If the player is telekinetic.
*/
boolean testPlayer(@NotNull Player player);
}

View File

@ -1,47 +0,0 @@
package com.willfp.eco.util.drops.telekinesis;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.ServicePriority;
import org.jetbrains.annotations.NotNull;
import java.util.function.Function;
@UtilityClass
public final class TelekinesisUtils {
/**
* The test service registered to bukkit.
*/
private final TelekinesisTests tests;
/**
* Test the player for telekinesis.
* <p>
* If any test returns true, so does this.
*
* @param player The player to test.
* @return If the player is telekinetic.
*/
public boolean testPlayer(@NotNull final Player player) {
return tests.testPlayer(player);
}
/**
* Register a new test to check against.
*
* @param test The test to register, where the boolean output is if the player is telekinetic.
*/
public void registerTest(@NotNull final Function<Player, Boolean> test) {
tests.registerTest(test);
}
static {
if (!Bukkit.getServicesManager().isProvidedFor(TelekinesisTests.class)) {
Bukkit.getServicesManager().register(TelekinesisTests.class, new EcoTelekinesisTests(), AbstractEcoPlugin.getInstance(), ServicePriority.Normal);
}
tests = Bukkit.getServicesManager().load(TelekinesisTests.class);
}
}

View File

@ -1,127 +0,0 @@
package com.willfp.eco.util.events.armorequip;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Arnah
* @since Jul 30, 2015
*/
public class ArmorEquipEvent extends PlayerEvent implements Cancellable {
private static final HandlerList HANDLERS = new HandlerList();
private boolean cancel = false;
private final EquipMethod equipType;
private final ArmorType type;
private ItemStack oldArmorPiece;
private ItemStack newArmorPiece;
public ArmorEquipEvent(@NotNull final Player player,
@Nullable final EquipMethod equipType,
@Nullable final ArmorType type,
@Nullable final ItemStack oldArmorPiece,
@Nullable final ItemStack newArmorPiece) {
super(player);
this.equipType = equipType;
this.type = type;
this.oldArmorPiece = oldArmorPiece;
this.newArmorPiece = newArmorPiece;
}
/**
* Gets a list of handlers handling this event.
*
* @return A list of handlers handling this event.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
public static HandlerList getHandlerList() {
return HANDLERS;
}
/**
* Sets if this event should be cancelled.
*
* @param cancel If this event should be cancelled.
*/
public final void setCancelled(final boolean cancel) {
this.cancel = cancel;
}
/**
* Gets if this event is cancelled.
*
* @return If this event is cancelled
*/
public final boolean isCancelled() {
return cancel;
}
public final ArmorType getType() {
return type;
}
public final ItemStack getOldArmorPiece() {
return oldArmorPiece;
}
public final void setOldArmorPiece(final ItemStack oldArmorPiece) {
this.oldArmorPiece = oldArmorPiece;
}
public final ItemStack getNewArmorPiece() {
return newArmorPiece;
}
public final void setNewArmorPiece(final ItemStack newArmorPiece) {
this.newArmorPiece = newArmorPiece;
}
public EquipMethod getMethod() {
return equipType;
}
public enum EquipMethod {
/**
* When you shift click an armor piece to equip or unequip
*/
SHIFT_CLICK,
/**
* When you drag and drop the item to equip or unequip
*/
DRAG,
/**
* When you manually equip or unequip the item. Use to be DRAG
*/
PICK_DROP,
/**
* When you right click an armor piece in the hotbar without the inventory open to equip.
*/
HOTBAR,
/**
* When you press the hotbar slot number while hovering over the armor slot to equip or unequip
*/
HOTBAR_SWAP,
/**
* When in range of a dispenser that shoots an armor piece to equip.<br>
* Requires the spigot version to have {@link org.bukkit.event.block.BlockDispenseArmorEvent} implemented.
*/
DISPENSER,
/**
* When an armor piece is removed due to it losing all durability.
*/
BROKE,
/**
* When you die causing all armor to unequip
*/
DEATH;
}
}

View File

@ -1,240 +0,0 @@
package com.willfp.eco.util.events.armorequip;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.InventoryType.SlotType;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerItemBreakEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.willfp.eco.util.events.armorequip.ArmorEquipEvent.EquipMethod;
/**
* @author Arnah
* @since Jul 30, 2015
*/
@SuppressWarnings("deprecation")
public class ArmorListener implements Listener {
//Event Priority is highest because other plugins might cancel the events before we check.
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public final void inventoryClick(@NotNull final InventoryClickEvent event) {
boolean shift = false;
boolean numberkey = false;
if (event.isCancelled()) {
return;
}
if (event.getAction() == InventoryAction.NOTHING) {
return;
}
if (event.getClick().equals(ClickType.SHIFT_LEFT) || event.getClick().equals(ClickType.SHIFT_RIGHT)) {
shift = true;
}
if (event.getClick().equals(ClickType.NUMBER_KEY)) {
numberkey = true;
}
if (event.getSlotType() != SlotType.ARMOR && event.getSlotType() != SlotType.QUICKBAR && event.getSlotType() != SlotType.CONTAINER) {
return;
}
if (event.getClickedInventory() != null && !event.getClickedInventory().getType().equals(InventoryType.PLAYER)) {
return;
}
if (!event.getInventory().getType().equals(InventoryType.CRAFTING) && !event.getInventory().getType().equals(InventoryType.PLAYER)) {
return;
}
if (!(event.getWhoClicked() instanceof Player)) {
return;
}
ArmorType newArmorType = ArmorType.matchType(shift ? event.getCurrentItem() : event.getCursor());
if (!shift && newArmorType != null && event.getRawSlot() != newArmorType.getSlot()) {
// Used for drag and drop checking to make sure you aren't trying to place a helmet in the boots slot.
return;
}
if (shift) {
newArmorType = ArmorType.matchType(event.getCurrentItem());
if (newArmorType != null) {
boolean equipping = true;
if (event.getRawSlot() == newArmorType.getSlot()) {
equipping = false;
}
if (newArmorType.equals(ArmorType.HELMET)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getHelmet()))
|| newArmorType.equals(ArmorType.CHESTPLATE)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getChestplate()))
|| newArmorType.equals(ArmorType.LEGGINGS)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getLeggings()))
|| newArmorType.equals(ArmorType.BOOTS)
&& (equipping == isAirOrNull(event.getWhoClicked().getInventory().getBoots()))) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(
(Player) event.getWhoClicked(),
EquipMethod.SHIFT_CLICK,
newArmorType,
equipping ? null : event.getCurrentItem(),
equipping ? event.getCurrentItem() : null
);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
event.setCancelled(true);
}
}
}
} else {
ItemStack newArmorPiece = event.getCursor();
ItemStack oldArmorPiece = event.getCurrentItem();
if (numberkey) {
if (event.getClickedInventory().getType().equals(InventoryType.PLAYER)) {
ItemStack hotbarItem = event.getClickedInventory().getItem(event.getHotbarButton());
if (!isAirOrNull(hotbarItem)) {
newArmorType = ArmorType.matchType(hotbarItem);
newArmorPiece = hotbarItem;
oldArmorPiece = event.getClickedInventory().getItem(event.getSlot());
} else {
newArmorType = ArmorType.matchType(!isAirOrNull(event.getCurrentItem()) ? event.getCurrentItem() : event.getCursor());
}
}
} else {
if (isAirOrNull(event.getCursor()) && !isAirOrNull(event.getCurrentItem())) {
newArmorType = ArmorType.matchType(event.getCurrentItem());
}
}
if (newArmorType != null && event.getRawSlot() == newArmorType.getSlot()) {
ArmorEquipEvent.EquipMethod method = ArmorEquipEvent.EquipMethod.PICK_DROP;
if (event.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberkey) {
method = ArmorEquipEvent.EquipMethod.HOTBAR_SWAP;
}
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), method, newArmorType, oldArmorPiece, newArmorPiece);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
event.setCancelled(true);
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST)
public void playerInteractEvent(@NotNull final PlayerInteractEvent e) {
if (e.useItemInHand().equals(Result.DENY)) {
return;
}
if (e.getAction() == Action.PHYSICAL) {
return;
}
if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) {
Player player = e.getPlayer();
if (!e.useInteractedBlock().equals(Result.DENY)) {
if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK && !player.isSneaking()) {
Material mat = e.getClickedBlock().getType();
}
}
ArmorType newArmorType = ArmorType.matchType(e.getItem());
if (newArmorType != null) {
if (newArmorType.equals(ArmorType.HELMET)
&& isAirOrNull(e.getPlayer().getInventory().getHelmet())
|| newArmorType.equals(ArmorType.CHESTPLATE)
&& isAirOrNull(e.getPlayer().getInventory().getChestplate())
|| newArmorType.equals(ArmorType.LEGGINGS)
&& isAirOrNull(e.getPlayer().getInventory().getLeggings())
|| newArmorType.equals(ArmorType.BOOTS)
&& isAirOrNull(e.getPlayer().getInventory().getBoots())) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), ArmorEquipEvent.EquipMethod.HOTBAR, ArmorType.matchType(e.getItem()), null, e.getItem());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
e.setCancelled(true);
player.updateInventory();
}
}
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void inventoryDrag(@NotNull final InventoryDragEvent event) {
// getType() seems to always be even.
// Old Cursor gives the item you are equipping
// Raw slot is the ArmorType slot
// Can't replace armor using this method making getCursor() useless.
ArmorType type = ArmorType.matchType(event.getOldCursor());
if (event.getRawSlots().isEmpty()) {
return;
}
if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), EquipMethod.DRAG, type, null, event.getOldCursor());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
event.setResult(Result.DENY);
event.setCancelled(true);
}
}
// Debug shit
}
@EventHandler
public void playerJoinEvent(@NotNull final PlayerJoinEvent event) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(event.getPlayer(), null, null, null, null);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
@EventHandler
public void playerRespawnEvent(@NotNull final PlayerRespawnEvent event) {
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(event.getPlayer(), null, null, null, null);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
}
@EventHandler
public void itemBreakEvent(@NotNull final PlayerItemBreakEvent event) {
ArmorType type = ArmorType.matchType(event.getBrokenItem());
if (type != null) {
Player p = event.getPlayer();
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, event.getBrokenItem(), null);
Bukkit.getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
ItemStack i = event.getBrokenItem().clone();
i.setAmount(1);
i.setDurability((short) (i.getDurability() - 1));
if (type.equals(ArmorType.HELMET)) {
p.getInventory().setHelmet(i);
} else if (type.equals(ArmorType.CHESTPLATE)) {
p.getInventory().setChestplate(i);
} else if (type.equals(ArmorType.LEGGINGS)) {
p.getInventory().setLeggings(i);
} else if (type.equals(ArmorType.BOOTS)) {
p.getInventory().setBoots(i);
}
}
}
}
@EventHandler
public void playerDeathEvent(@NotNull final PlayerDeathEvent event) {
Player p = event.getEntity();
if (event.getKeepInventory()) {
return;
}
for (ItemStack i : p.getInventory().getArmorContents()) {
if (!isAirOrNull(i)) {
Bukkit.getPluginManager().callEvent(new ArmorEquipEvent(p, EquipMethod.DEATH, ArmorType.matchType(i), i, null));
// No way to cancel a death event.
}
}
}
public static boolean isAirOrNull(@Nullable final ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
}

View File

@ -1,49 +0,0 @@
package com.willfp.eco.util.events.armorequip;
import org.bukkit.inventory.ItemStack;
/**
* @author Arnah
* @since Jul 30, 2015
*/
public enum ArmorType {
HELMET(5),
CHESTPLATE(6),
LEGGINGS(7),
BOOTS(8);
private final int slot;
ArmorType(final int slot) {
this.slot = slot;
}
/**
* Attempts to match the ArmorType for the specified ItemStack.
*
* @param itemStack The ItemStack to parse the type of.
*
* @return The parsed ArmorType, or null if not found.
*/
public static ArmorType matchType(final ItemStack itemStack) {
if (ArmorListener.isAirOrNull(itemStack)) {
return null;
}
String type = itemStack.getType().name();
if (type.endsWith("_HELMET") || type.endsWith("_SKULL") || type.endsWith("PLAYER_HEAD")) {
return HELMET;
} else if (type.endsWith("_CHESTPLATE") || type.endsWith("ELYTRA")) {
return CHESTPLATE;
} else if (type.endsWith("_LEGGINGS")) {
return LEGGINGS;
} else if (type.endsWith("_BOOTS")) {
return BOOTS;
} else {
return null;
}
}
public int getSlot() {
return slot;
}
}

View File

@ -1,27 +0,0 @@
package com.willfp.eco.util.events.armorequip;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockDispenseArmorEvent;
import org.jetbrains.annotations.NotNull;
/**
* @author Arnah
* @since Feb 08, 2019
*/
public class DispenserArmorListener implements Listener {
@EventHandler
public void dispenseArmorEvent(@NotNull final BlockDispenseArmorEvent event) {
ArmorType type = ArmorType.matchType(event.getItem());
if (type != null && event.getTargetEntity() instanceof Player) {
Player p = (Player) event.getTargetEntity();
ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, ArmorEquipEvent.EquipMethod.DISPENSER, type, null, event.getItem());
Bukkit.getPluginManager().callEvent(armorEquipEvent);
if (armorEquipEvent.isCancelled()) {
event.setCancelled(true);
}
}
}
}

View File

@ -1,60 +0,0 @@
package com.willfp.eco.util.events.entitydeathbyentity;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import java.util.List;
class EntityDeathByEntityBuilder {
/**
* The killed {@link LivingEntity}.
*/
@Getter
@Setter
private LivingEntity victim = null;
/**
* The killer.
*/
@Getter
@Setter
private Entity damager;
/**
* The associated {@link EntityDeathEvent}.
*/
@Getter
@Setter
private EntityDeathEvent deathEvent;
/**
* The drops to create.
*/
@Getter
@Setter
private List<ItemStack> drops;
/**
* The experience to drop.
*/
@Getter
@Setter
private int xp = 0;
public void push() {
Validate.notNull(victim);
Validate.notNull(damager);
Validate.notNull(drops);
Validate.notNull(deathEvent);
EntityDeathByEntityEvent event = new EntityDeathByEntityEvent(victim, damager, drops, xp, deathEvent);
Bukkit.getPluginManager().callEvent(event);
}
}

View File

@ -1,92 +0,0 @@
package com.willfp.eco.util.events.entitydeathbyentity;
import lombok.Getter;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Event triggered when entity is killed by entity.
*/
public class EntityDeathByEntityEvent extends Event {
/**
* Internal, for bukkit.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* The {@link LivingEntity} killed.
*/
@Getter
private final LivingEntity victim;
/**
* The {@link Entity} that killed.
*/
@Getter
private final Entity killer;
/**
* The associated {@link EntityDeathEvent}.
*/
@Getter
private final EntityDeathEvent deathEvent;
/**
* The entity drops.
*/
@Getter
private final List<ItemStack> drops;
/**
* The xp to drop.
*/
@Getter
private final int xp;
/**
* Create event based off parameters.
*
* @param victim The killed entity
* @param killer The killer
* @param drops The item drops
* @param xp The amount of xp to drop
* @param deathEvent The associated {@link EntityDeathEvent}
*/
public EntityDeathByEntityEvent(@NotNull final LivingEntity victim,
@NotNull final Entity killer,
@NotNull final List<ItemStack> drops,
final int xp,
@NotNull final EntityDeathEvent deathEvent) {
this.victim = victim;
this.killer = killer;
this.drops = drops;
this.xp = xp;
this.deathEvent = deathEvent;
}
/**
* Internal bukkit.
*
* @return Get the handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
* Internal bukkit.
*
* @return The handlers.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@ -1,96 +0,0 @@
package com.willfp.eco.util.events.entitydeathbyentity;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
public class EntityDeathByEntityListeners extends PluginDependent implements Listener {
/**
* The events currently being built.
*/
private final Set<EntityDeathByEntityBuilder> events = new HashSet<>();
/**
* Create a listener associated with an {@link AbstractEcoPlugin}.
*
* @param plugin The plugin to associate with.
*/
@ApiStatus.Internal
public EntityDeathByEntityListeners(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Called when an entity is damaged by another entity.
* Used to find the damager.
*
* @param event The event to listen for.
*/
@EventHandler(priority = EventPriority.HIGH)
public void onEntityDamage(@NotNull final EntityDamageByEntityEvent event) {
if (!(event.getEntity() instanceof LivingEntity)) {
return;
}
LivingEntity victim = (LivingEntity) event.getEntity();
if (victim.getHealth() > event.getFinalDamage()) {
return;
}
EntityDeathByEntityBuilder builtEvent = new EntityDeathByEntityBuilder();
builtEvent.setVictim(victim);
builtEvent.setDamager(event.getDamager());
events.add(builtEvent);
this.getPlugin().getScheduler().runLater(() -> events.remove(builtEvent), 1);
}
/**
* Called when an entity is killed.
* Used to find the killer and associate the event.
*
* @param event The event to listen for.
*/
@EventHandler
public void onEntityDeath(@NotNull final EntityDeathEvent event) {
LivingEntity victim = event.getEntity();
List<ItemStack> drops = event.getDrops();
int xp = event.getDroppedExp();
AtomicReference<EntityDeathByEntityBuilder> atomicBuiltEvent = new AtomicReference<>(null);
EntityDeathByEntityBuilder builtEvent;
events.forEach(deathByEntityEvent -> {
if (deathByEntityEvent.getVictim().equals(victim)) {
atomicBuiltEvent.set(deathByEntityEvent);
}
});
if (atomicBuiltEvent.get() == null) {
return;
}
builtEvent = atomicBuiltEvent.get();
events.remove(builtEvent);
builtEvent.setDrops(drops);
builtEvent.setXp(xp);
builtEvent.setDeathEvent(event);
builtEvent.push();
}
}

View File

@ -1,74 +0,0 @@
package com.willfp.eco.util.events.naturalexpgainevent;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.jetbrains.annotations.NotNull;
class NaturalExpGainBuilder {
/**
* If the event has been cancelled and no experience should be given.
*/
@Getter
@Setter
private boolean cancelled = false;
/**
* The linked {@link PlayerExpChangeEvent}.
*/
@Getter
@Setter
private PlayerExpChangeEvent event;
/**
* The location of the event.
*/
@Getter
@Setter
private Location location;
/**
* The reason why the event was built.
*/
@Getter
@Setter
private BuildReason reason;
/**
* Build a new {@link NaturalExpGainEvent} given a specific reason.
*
* @param reason The {@link BuildReason}.
*/
NaturalExpGainBuilder(@NotNull final BuildReason reason) {
this.reason = reason;
}
/**
* Call the event on the server.
*/
public void push() {
Validate.notNull(event);
if (this.cancelled) {
return;
}
NaturalExpGainEvent naturalExpGainEvent = new NaturalExpGainEvent(event);
Bukkit.getPluginManager().callEvent(naturalExpGainEvent);
}
public enum BuildReason {
/**
* If the event was triggered by an experience bottle.
*/
BOTTLE,
/**
* If the event was triggered by a natural experience change.
*/
PLAYER
}
}

View File

@ -1,49 +0,0 @@
package com.willfp.eco.util.events.naturalexpgainevent;
import lombok.Getter;
import org.bukkit.event.Event;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.jetbrains.annotations.NotNull;
public class NaturalExpGainEvent extends Event {
/**
* Internal bukkit.
*/
private static final HandlerList HANDLERS = new HandlerList();
/**
* The associated {@link PlayerExpChangeEvent}.
* Use this to modify event parameters.
*/
@Getter
private final PlayerExpChangeEvent expChangeEvent;
/**
* Create event based off parameters.
*
* @param event The associated PlayerExpChangeEvent.
*/
public NaturalExpGainEvent(@NotNull final PlayerExpChangeEvent event) {
this.expChangeEvent = event;
}
/**
* Internal bukkit.
*
* @return The handlers.
*/
@Override
public @NotNull HandlerList getHandlers() {
return HANDLERS;
}
/**
* Internal bukkit.
*
* @return The handlers.
*/
public static HandlerList getHandlerList() {
return HANDLERS;
}
}

View File

@ -1,63 +0,0 @@
package com.willfp.eco.util.events.naturalexpgainevent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.ExpBottleEvent;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
public class NaturalExpGainListeners implements Listener {
/**
* The events currently being built.
*/
private final Set<NaturalExpGainBuilder> events = new HashSet<>();
/**
* Called when the player's xp level changes.
* Used to store properties.
*
* @param event The event to listen for.
*/
@EventHandler
public void playerChange(@NotNull final PlayerExpChangeEvent event) {
NaturalExpGainBuilder builder = new NaturalExpGainBuilder(NaturalExpGainBuilder.BuildReason.PLAYER);
builder.setEvent(event);
NaturalExpGainBuilder toRemove = null;
for (NaturalExpGainBuilder searchBuilder : events) {
if (!searchBuilder.getLocation().getWorld().equals(event.getPlayer().getLocation().getWorld())) {
continue;
}
if (searchBuilder.getReason().equals(NaturalExpGainBuilder.BuildReason.BOTTLE) && searchBuilder.getLocation().distanceSquared(event.getPlayer().getLocation()) > 52) {
toRemove = searchBuilder;
}
}
if (toRemove != null) {
events.remove(toRemove);
return;
}
builder.setEvent(event);
builder.push();
events.remove(builder);
}
/**
* Called when an xp bottle breaks.
* Used to remove some built events to ensure only natural events are pushed.
*
* @param event The even to listen for.
*/
@EventHandler
public void onExpBottle(@NotNull final ExpBottleEvent event) {
NaturalExpGainBuilder builtEvent = new NaturalExpGainBuilder(NaturalExpGainBuilder.BuildReason.BOTTLE);
builtEvent.setLocation(event.getEntity().getLocation());
events.add(builtEvent);
}
}

View File

@ -1,107 +0,0 @@
package com.willfp.eco.util.extensions;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.AccessLevel;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
public abstract class Extension {
/**
* The {@link AbstractEcoPlugin} that this extension is for.
*/
@Getter(AccessLevel.PROTECTED)
private final AbstractEcoPlugin plugin = AbstractEcoPlugin.getInstance();
/**
* Metadata containing version and name.
*/
private ExtensionMetadata metadata = null;
/**
* Method to validate metadata and enable extension.
*/
public final void enable() {
Validate.notNull(metadata, "Metadata cannot be null!");
this.onEnable();
}
/**
* Method to disable extension.
*/
public final void disable() {
this.onDisable();
}
/**
* Called on enabling Extension.
*/
protected abstract void onEnable();
/**
* Called when Extension is disabled.
*/
protected abstract void onDisable();
/**
* Set the metadata of the extension.
* <p>
* Must be called before enabling.
*
* @param metadata The metadata to set.
*/
public final void setMetadata(@NotNull final ExtensionMetadata metadata) {
this.metadata = metadata;
}
/**
* Get the name of the extension.
*
* @return The name of the metadata attached to the extension.
*/
public final String getName() {
Validate.notNull(metadata, "Metadata cannot be null!");
return this.metadata.name;
}
/**
* Get the version of the extension.
*
* @return The version of the metadata attached to the extension.
*/
public final String getVersion() {
Validate.notNull(metadata, "Metadata cannot be null!");
return this.metadata.version;
}
/**
* Wrapper for the string and version of the extension.
* Contains versions and name.
* Designed for internal use.
*/
@ApiStatus.Internal
public static final class ExtensionMetadata {
/**
* The version of the extension.
*/
private final @NotNull String version;
/**
* The extension's name.
*/
private final @NotNull String name;
/**
* Create a new extension metadata.
*
* @param version The version for the extension to be.
* @param name The name of the extension.
*/
public ExtensionMetadata(@NotNull final String version,
@NotNull final String name) {
this.version = version;
this.name = name;
}
}
}

View File

@ -1,22 +0,0 @@
package com.willfp.eco.util.extensions;
import org.jetbrains.annotations.NotNull;
/**
* Called when the extension is made incorrectly.
*/
public class MalformedExtensionException extends RuntimeException {
/**
* Create a new MalformedExtensionException.
* <p>
* Potential causes include:
* Missing or invalid extension.yml.
* Invalid filetype.
*
* @param errorMessage The error message to show.
*/
public MalformedExtensionException(@NotNull final String errorMessage) {
super(errorMessage);
}
}

View File

@ -1,145 +0,0 @@
package com.willfp.eco.util.extensions.loader;
import com.willfp.eco.util.extensions.Extension;
import com.willfp.eco.util.extensions.MalformedExtensionException;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
* Concrete implementation of {@link ExtensionLoader}.
*/
public class EcoExtensionLoader extends PluginDependent implements ExtensionLoader {
/**
* All currently loaded extensions.
*/
private final Set<Extension> extensions = new HashSet<>();
/**
* Create a new extension loader and link it to a specific {@link AbstractEcoPlugin}.
*
* @param plugin The plugin to manage
*/
public EcoExtensionLoader(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Load all present extensions.
*/
@Override
public void loadExtensions() {
File dir = new File(this.getPlugin().getDataFolder(), "/extensions");
if (!dir.exists()) {
dir.mkdirs();
}
File[] extensionJars = dir.listFiles();
if (extensionJars == null) {
return;
}
for (File extensionJar : extensionJars) {
if (!extensionJar.isFile()) {
continue;
}
try {
loadExtension(extensionJar);
} catch (MalformedExtensionException e) {
this.getPlugin().getLog().error(extensionJar.getName() + " caused MalformedExtensionException: " + e.getMessage());
}
}
}
private void loadExtension(@NotNull final File extensionJar) {
URL url = null;
try {
url = extensionJar.toURI().toURL();
} catch (MalformedURLException e) {
e.printStackTrace();
}
ClassLoader cl = new URLClassLoader(new URL[]{url}, this.getPlugin().getClass().getClassLoader());
InputStream ymlIn = cl.getResourceAsStream("extension.yml");
if (ymlIn == null) {
throw new MalformedExtensionException("No extension.yml found in " + extensionJar.getName());
}
YamlConfiguration extensionYml = YamlConfiguration.loadConfiguration(new InputStreamReader(ymlIn));
Set<String> keys = extensionYml.getKeys(false);
ArrayList<String> required = new ArrayList<>(Arrays.asList("main", "name", "version"));
required.removeAll(keys);
if (!required.isEmpty()) {
throw new MalformedExtensionException("Invalid extension.yml found in " + extensionJar.getName() + " - Missing: " + String.join(", ", required));
}
String mainClass = extensionYml.getString("main");
String name = extensionYml.getString("name");
String version = extensionYml.getString("version");
Extension.ExtensionMetadata metadata = new Extension.ExtensionMetadata(version, name);
Class<?> cls;
Object object = null;
try {
cls = cl.loadClass(mainClass);
object = cls.getConstructor().newInstance();
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
if (!(object instanceof Extension)) {
throw new MalformedExtensionException(extensionJar.getName() + " is invalid");
}
Extension extension = (Extension) object;
extension.setMetadata(metadata);
extension.enable();
extensions.add(extension);
}
/**
* Unload all existing extensions.
*/
@Override
public void unloadExtensions() {
extensions.forEach(Extension::disable);
extensions.clear();
}
/**
* Unloads, then loads all extensions.
*/
@Override
public void reloadExtensions() {
unloadExtensions();
loadExtensions();
}
/**
* Returns all loaded extensions.
*
* @return A {@link Set} of all loaded extensions.
*/
@Override
public Set<Extension> getLoadedExtensions() {
return extensions;
}
}

View File

@ -1,34 +0,0 @@
package com.willfp.eco.util.extensions.loader;
import com.willfp.eco.util.extensions.Extension;
import java.util.Set;
/**
* Interface for extension loader.
* Some external plugins may modify extension loading for internal server purposes.
*/
public interface ExtensionLoader {
/**
* Load all extensions.
*/
void loadExtensions();
/**
* Unload all loaded extensions.
*/
void unloadExtensions();
/**
* Reload all extensions.
*/
void reloadExtensions();
/**
* Retrieve a set of all loaded extensions.
*
* @return An {@link Set<Extension>} of all loaded extensions.
*/
Set<Extension> getLoadedExtensions();
}

View File

@ -1,9 +0,0 @@
package com.willfp.eco.util.integrations;
public interface Integration {
/**
* Get the name of integration.
* @return The name.
*/
String getPluginName();
}

View File

@ -1,36 +0,0 @@
package com.willfp.eco.util.integrations;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
public class IntegrationLoader {
/**
* The lambda to be ran if the plugin is present.
*/
private final Runnable runnable;
/**
* The plugin to require to load the integration.
*/
@Getter
private final String pluginName;
/**
* Create a new Integration Loader.
*
* @param pluginName The plugin to require.
* @param onLoad The lambda to be ran if the plugin is present.
*/
public IntegrationLoader(@NotNull final String pluginName,
@NotNull final Runnable onLoad) {
this.runnable = onLoad;
this.pluginName = pluginName;
}
/**
* Load the integration.
*/
public void load() {
runnable.run();
}
}

View File

@ -1,56 +0,0 @@
package com.willfp.eco.util.integrations.anticheat;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
@UtilityClass
public class AnticheatManager {
/**
* The linked {@link AbstractEcoPlugin} to register anticheat listeners to.
*/
private final AbstractEcoPlugin plugin = AbstractEcoPlugin.getInstance();
/**
* A set of all registered anticheats.
*/
private final Set<AnticheatWrapper> anticheats = new HashSet<>();
/**
* Register a new anticheat.
*
* @param anticheat The anticheat to register.
*/
public void register(@NotNull final AnticheatWrapper anticheat) {
if (anticheat instanceof Listener) {
plugin.getEventManager().registerListener((Listener) anticheat);
}
anticheats.add(anticheat);
}
/**
* Exempt a player from triggering anticheats.
*
* @param player The player to exempt.
*/
public void exemptPlayer(@NotNull final Player player) {
anticheats.forEach(anticheat -> anticheat.exempt(player));
}
/**
* Unexempt a player from triggering anticheats.
* This is ran a tick after it is called to ensure that there are no event timing conflicts.
*
* @param player The player to remove the exemption.
*/
public void unexemptPlayer(@NotNull final Player player) {
plugin.getScheduler().runLater(() -> {
anticheats.forEach(anticheat -> anticheat.unexempt(player));
}, 1);
}
}

View File

@ -1,21 +0,0 @@
package com.willfp.eco.util.integrations.anticheat;
import com.willfp.eco.util.integrations.Integration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public interface AnticheatWrapper extends Integration {
/**
* Exempt a player from checks.
*
* @param player The player to exempt.
*/
void exempt(@NotNull Player player);
/**
* Unexempt a player from checks.
*
* @param player The player to unexempt.
*/
void unexempt(@NotNull Player player);
}

View File

@ -1,38 +0,0 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import me.konsolas.aac.api.AACAPI;
import me.konsolas.aac.api.AACExemption;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.Objects;
public class AnticheatAAC implements AnticheatWrapper, Listener {
/**
* AAC exemption for EcoEnchants.
*/
private final AACExemption ecoEnchantsExemption = new AACExemption("EcoEnchants");
/**
* AAC api.
*/
private final AACAPI api = Objects.requireNonNull(Bukkit.getServicesManager().load(AACAPI.class));
@Override
public String getPluginName() {
return "AAC";
}
@Override
public void exempt(@NotNull final Player player) {
api.addExemption(player, ecoEnchantsExemption);
}
@Override
public void unexempt(@NotNull final Player player) {
api.removeExemption(player, ecoEnchantsExemption);
}
}

View File

@ -1,44 +0,0 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import me.rerere.matrix.api.events.PlayerViolationEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class AnticheatMatrix implements AnticheatWrapper, Listener {
/**
* Currently exempt players.
*/
private final Set<UUID> exempt = new HashSet<>();
@Override
public String getPluginName() {
return "Matrix";
}
@Override
public void exempt(@NotNull final Player player) {
this.exempt.add(player.getUniqueId());
}
@Override
public void unexempt(@NotNull final Player player) {
this.exempt.remove(player.getUniqueId());
}
@EventHandler(priority = EventPriority.LOWEST)
private void onViolate(@NotNull final PlayerViolationEvent event) {
if (!exempt.contains(event.getPlayer().getUniqueId())) {
return;
}
event.setCancelled(true);
}
}

View File

@ -1,41 +0,0 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.hooks.NCPExemptionManager;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class AnticheatNCP implements AnticheatWrapper {
/**
* Currently exempt players.
*/
private final Set<UUID> exempt = new HashSet<>();
@Override
public String getPluginName() {
return "NCP";
}
@Override
public void exempt(@NotNull final Player player) {
if (!NCPExemptionManager.isExempted(player, CheckType.ALL)) {
return;
}
if (exempt.add(player.getUniqueId())) {
NCPExemptionManager.exemptPermanently(player, CheckType.ALL);
}
}
@Override
public void unexempt(@NotNull final Player player) {
if (exempt.remove(player.getUniqueId())) {
NCPExemptionManager.unexempt(player, CheckType.ALL);
}
}
}

View File

@ -1,44 +0,0 @@
package com.willfp.eco.util.integrations.anticheat.plugins;
import com.willfp.eco.util.integrations.anticheat.AnticheatWrapper;
import me.vagdedes.spartan.api.PlayerViolationEvent;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
public class AnticheatSpartan implements AnticheatWrapper, Listener {
/**
* Currently exempt players.
*/
private final Set<UUID> exempt = new HashSet<>();
@Override
public String getPluginName() {
return "Spartan";
}
@Override
public void exempt(@NotNull final Player player) {
this.exempt.add(player.getUniqueId());
}
@Override
public void unexempt(@NotNull final Player player) {
this.exempt.remove(player.getUniqueId());
}
@EventHandler(priority = EventPriority.LOWEST)
private void onViolate(@NotNull final PlayerViolationEvent event) {
if (!exempt.contains(event.getPlayer().getUniqueId())) {
return;
}
event.setCancelled(true);
}
}

View File

@ -1,76 +0,0 @@
package com.willfp.eco.util.integrations.antigrief;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
@UtilityClass
public class AntigriefManager {
/**
* Registered antigriefs.
*/
private final Set<AntigriefWrapper> registered = new HashSet<>();
/**
* Register a new AntiGrief/Land Management integration.
*
* @param antigrief The integration to register.
*/
public void register(@NotNull final AntigriefWrapper antigrief) {
registered.add(antigrief);
}
/**
* Can player break block.
*
* @param player The player.
* @param block The block.
* @return If player can break block.
*/
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
return registered.stream().allMatch(antigriefWrapper -> antigriefWrapper.canBreakBlock(player, block));
}
/**
* Can player create explosion at location.
*
* @param player The player.
* @param location The location.
* @return If player can create explosion.
*/
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
return registered.stream().allMatch(antigriefWrapper -> antigriefWrapper.canCreateExplosion(player, location));
}
/**
* Can player place block.
*
* @param player The player.
* @param block The block.
* @return If player can place block.
*/
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
return registered.stream().allMatch(antigriefWrapper -> antigriefWrapper.canPlaceBlock(player, block));
}
/**
* Can player injure living entity.
*
* @param player The player.
* @param victim The victim.
* @return If player can injure.
*/
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
return registered.stream().allMatch(antigriefWrapper -> antigriefWrapper.canInjure(player, victim));
}
}

View File

@ -1,45 +0,0 @@
package com.willfp.eco.util.integrations.antigrief;
import com.willfp.eco.util.integrations.Integration;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
public interface AntigriefWrapper extends Integration {
/**
* Can player break block.
*
* @param player The player.
* @param block The block.
* @return If player cna break block.
*/
boolean canBreakBlock(Player player, Block block);
/**
* Can player create explosion at location.
*
* @param player The player.
* @param location The location.
* @return If player can create explosion.
*/
boolean canCreateExplosion(Player player, Location location);
/**
* Can player place block.
*
* @param player The player.
* @param block The block.
* @return If player can place block.
*/
boolean canPlaceBlock(Player player, Block block);
/**
* Can player injure living entity.
*
* @param player The player.
* @param victim The victim.
* @return If player can injure.
*/
boolean canInjure(Player player, LivingEntity victim);
}

View File

@ -1,75 +0,0 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.FPlayers;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.perms.PermissibleAction;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class AntigriefFactionsUUID implements AntigriefWrapper {
@Override
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
FPlayer fplayer = FPlayers.getInstance().getByPlayer(player);
FLocation flocation = new FLocation(block.getLocation());
Faction faction = Board.getInstance().getFactionAt(flocation);
if (!faction.hasAccess(fplayer, PermissibleAction.DESTROY)) {
return fplayer.isAdminBypassing();
}
return true;
}
@Override
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
FLocation flocation = new FLocation(location);
Faction faction = Board.getInstance().getFactionAt(flocation);
return !faction.noExplosionsInTerritory();
}
@Override
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
FPlayer fplayer = FPlayers.getInstance().getByPlayer(player);
FLocation flocation = new FLocation(block.getLocation());
Faction faction = Board.getInstance().getFactionAt(flocation);
if (!faction.hasAccess(fplayer, PermissibleAction.BUILD)) {
return fplayer.isAdminBypassing();
}
return true;
}
@Override
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
FPlayer fplayer = FPlayers.getInstance().getByPlayer(player);
FLocation flocation = new FLocation(victim.getLocation());
Faction faction = Board.getInstance().getFactionAt(flocation);
if (victim instanceof Player) {
if (faction.isPeaceful()) {
return fplayer.isAdminBypassing();
}
} else {
if (faction.hasAccess(fplayer, PermissibleAction.DESTROY)) {
return fplayer.isAdminBypassing();
}
}
return true;
}
@Override
public String getPluginName() {
return "FactionsUUID";
}
}

View File

@ -1,61 +0,0 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import me.ryanhamshire.GriefPrevention.Claim;
import me.ryanhamshire.GriefPrevention.GriefPrevention;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class AntigriefGriefPrevention implements AntigriefWrapper {
@Override
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(block.getLocation(), false, null);
if (claim != null) {
return claim.allowBreak(player, block.getType()) == null;
}
return true;
}
@Override
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(location, false, null);
if (claim != null) {
return claim.areExplosivesAllowed;
}
return true;
}
@Override
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(block.getLocation(), false, null);
if (claim != null) {
return claim.allowBuild(player, block.getType()) == null;
}
return true;
}
@Override
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(victim.getLocation(), false, null);
if (victim instanceof Player) {
return claim == null;
} else {
if (claim != null && claim.ownerID != null) {
return claim.ownerID.equals(player.getUniqueId());
}
return true;
}
}
@Override
public String getPluginName() {
return "GriefPrevention";
}
}

View File

@ -1,73 +0,0 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.inventory.EquipmentSlot;
import org.jetbrains.annotations.NotNull;
import org.kingdoms.constants.kingdom.Kingdom;
import org.kingdoms.constants.land.Land;
import org.kingdoms.managers.PvPManager;
import org.kingdoms.managers.land.LandManager;
public class AntigriefKingdoms implements AntigriefWrapper {
@Override
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
BlockBreakEvent event = new BlockBreakEvent(block, player);
LandManager.onBreak(event);
return !event.isCancelled();
}
@Override
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
Land land = Land.getLand(location);
if (land == null) {
return true;
}
if (!land.isClaimed()) {
return true;
}
Kingdom kingdom = land.getKingdom();
return kingdom.isMember(player);
}
@Override
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
Block placedOn = block.getRelative(0, -1, 0);
BlockPlaceEvent event = new BlockPlaceEvent(block, block.getState(), placedOn, player.getInventory().getItemInMainHand(), player, true, EquipmentSlot.HAND);
LandManager.onPlace(event);
return !event.isCancelled();
}
@Override
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
if (victim instanceof Player) {
return PvPManager.canFight(player, (Player) victim);
} else {
Land land = Land.getLand(victim.getLocation());
if (land == null) {
return true;
}
if (!land.isClaimed()) {
return true;
}
Kingdom kingdom = land.getKingdom();
return kingdom.isMember(player);
}
}
@Override
public String getPluginName() {
return "Kingdoms";
}
}

View File

@ -1,80 +0,0 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import me.angeschossen.lands.api.integration.LandsIntegration;
import me.angeschossen.lands.api.land.Area;
import me.angeschossen.lands.api.role.enums.RoleSetting;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class AntigriefLands extends PluginDependent implements AntigriefWrapper {
/**
* Lands integration.
*/
private final LandsIntegration landsIntegration = new LandsIntegration(this.getPlugin());
/**
* Instantiate new lands integration.
*
* @param plugin The integration provider.
*/
public AntigriefLands(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
@Override
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
Area area = landsIntegration.getAreaByLoc(block.getLocation());
if (area != null) {
return area.canSetting(player, RoleSetting.BLOCK_BREAK, false);
}
return true;
}
@Override
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
Area area = landsIntegration.getAreaByLoc(location);
if (area != null) {
return area.canSetting(player, RoleSetting.BLOCK_IGNITE, false);
}
return true;
}
@Override
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
Area area = landsIntegration.getAreaByLoc(block.getLocation());
if (area != null) {
return area.canSetting(player, RoleSetting.BLOCK_PLACE, false);
}
return true;
}
@Override
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
Area area = landsIntegration.getAreaByLoc(victim.getLocation());
if (victim instanceof Player) {
if (area != null) {
return area.canSetting(player, RoleSetting.ATTACK_PLAYER, false);
}
} else {
if (area != null) {
return area.canSetting(player, RoleSetting.ATTACK_ANIMAL, false);
}
}
return true;
}
@Override
public String getPluginName() {
return "Lands";
}
}

View File

@ -1,59 +0,0 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
import com.palmergames.bukkit.towny.object.Town;
import com.palmergames.bukkit.towny.object.TownyPermission;
import com.palmergames.bukkit.towny.object.WorldCoord;
import com.palmergames.bukkit.towny.utils.PlayerCacheUtil;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class AntigriefTowny implements AntigriefWrapper {
@Override
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
return PlayerCacheUtil.getCachePermission(player, block.getLocation(), block.getType(), TownyPermission.ActionType.DESTROY);
}
@Override
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
return PlayerCacheUtil.getCachePermission(player, location, Material.TNT, TownyPermission.ActionType.ITEM_USE);
}
@Override
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
return PlayerCacheUtil.getCachePermission(player, block.getLocation(), block.getType(), TownyPermission.ActionType.BUILD);
}
@Override
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
if (victim instanceof Player) {
try {
Town town = WorldCoord.parseWorldCoord(victim.getLocation()).getTownBlock().getTown();
return town.isPVP();
} catch (Exception ignored) {
// If exception, no town was found, thus return true.
}
} else {
try {
Town town = WorldCoord.parseWorldCoord(victim.getLocation()).getTownBlock().getTown();
return town.hasMobs();
} catch (Exception ignored) {
// If exception, no town was found, thus return true.
}
}
return true;
}
@Override
public String getPluginName() {
return "Towny";
}
}

View File

@ -1,85 +0,0 @@
package com.willfp.eco.util.integrations.antigrief.plugins;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import com.willfp.eco.util.integrations.antigrief.AntigriefWrapper;
import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class AntigriefWorldGuard implements AntigriefWrapper {
@Override
public boolean canBreakBlock(@NotNull final Player player,
@NotNull final Block block) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery();
if (query.queryState(BukkitAdapter.adapt(block.getLocation()), localPlayer, Flags.BUILD) == StateFlag.State.DENY) {
return WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(localPlayer, BukkitAdapter.adapt(block.getWorld()));
}
return true;
}
@Override
public boolean canCreateExplosion(@NotNull final Player player,
@NotNull final Location location) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery();
World world = location.getWorld();
Validate.notNull(world, "World cannot be null!");
if (query.queryState(BukkitAdapter.adapt(location), localPlayer, Flags.OTHER_EXPLOSION) == StateFlag.State.DENY) {
return WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(localPlayer, BukkitAdapter.adapt(world));
}
return true;
}
@Override
public boolean canPlaceBlock(@NotNull final Player player,
@NotNull final Block block) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery();
if (query.queryState(BukkitAdapter.adapt(block.getLocation()), localPlayer, Flags.BLOCK_PLACE) == StateFlag.State.DENY) {
return WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(localPlayer, BukkitAdapter.adapt(block.getWorld()));
}
return true;
}
@Override
public boolean canInjure(@NotNull final Player player,
@NotNull final LivingEntity victim) {
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery();
if (victim instanceof Player) {
if (query.queryState(BukkitAdapter.adapt(victim.getLocation()), localPlayer, Flags.PVP) == StateFlag.State.DENY) {
return WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(localPlayer, BukkitAdapter.adapt(player.getWorld()));
}
} else {
if (query.queryState(BukkitAdapter.adapt(victim.getLocation()), localPlayer, Flags.DAMAGE_ANIMALS) == StateFlag.State.DENY) {
return WorldGuard.getInstance().getPlatform().getSessionManager().hasBypass(localPlayer, BukkitAdapter.adapt(player.getWorld()));
}
}
return true;
}
@Override
public String getPluginName() {
return "WorldGuard";
}
}

View File

@ -1,75 +0,0 @@
package com.willfp.eco.util.integrations.placeholder;
import lombok.Getter;
import org.apache.commons.lang.Validate;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
public class PlaceholderEntry {
/**
* The name of the placeholder, used in lookups.
*/
@Getter
private final String identifier;
/**
* The lambda to retrieve the output of the placeholder given a player.
*/
private final Function<Player, String> function;
/**
* If the placeholder requires a player to lookup.
*/
private final boolean requiresPlayer;
/**
* Create a placeholder entry that doesn't require a player.
*
* @param identifier The identifier of the placeholder.
* @param function A lambda to get the result of the placeholder given a player.
*/
public PlaceholderEntry(@NotNull final String identifier,
@NotNull final Function<Player, String> function) {
this(identifier, function, false);
}
/**
* Create a placeholder entry that may require a player.
*
* @param identifier The identifier of the placeholder.
* @param function A lambda to get the result of the placeholder.
* @param requiresPlayer If the placeholder requires a player.
*/
public PlaceholderEntry(@NotNull final String identifier,
@NotNull final Function<Player, String> function,
final boolean requiresPlayer) {
this.identifier = identifier;
this.function = function;
this.requiresPlayer = requiresPlayer;
}
/**
* Get the result of the placeholder with respect to a player.
*
* @param player The player to translate with respect to.
* @return The result of the placeholder.
*/
public String getResult(@Nullable final Player player) {
if (player == null) {
Validate.isTrue(!requiresPlayer, "null player passed to requiresPlayer placeholder.");
}
return this.function.apply(player);
}
/**
* Get if the placeholder requires a player to get a result.
*
* @return If the placeholder requires a player.
*/
public boolean requiresPlayer() {
return requiresPlayer;
}
}

View File

@ -1,24 +0,0 @@
package com.willfp.eco.util.integrations.placeholder;
import com.willfp.eco.util.integrations.Integration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface PlaceholderIntegration extends Integration {
/**
* Register the integration with the specified plugin.
* Not to be confused with internal registration in {@link PlaceholderManager#addIntegration(PlaceholderIntegration)}.
*/
void registerIntegration();
/**
* Translate all the placeholders in a string with respect to a player.
*
* @param text The text to translate.
* @param player The player to translate with respect to.
* @return The string, translated.
*/
String translate(@NotNull String text,
@Nullable Player player);
}

View File

@ -1,78 +0,0 @@
package com.willfp.eco.util.integrations.placeholder;
import lombok.experimental.UtilityClass;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@UtilityClass
public class PlaceholderManager {
/**
* All registered placeholders.
*/
private static final Set<PlaceholderEntry> REGISTERED_PLACEHOLDERS = new HashSet<>();
/**
* All registered placeholder integrations.
*/
private static final Set<PlaceholderIntegration> REGISTERED_INTEGRATIONS = new HashSet<>();
/**
* Register a new placeholder integration.
*
* @param integration The {@link PlaceholderIntegration} to register.
*/
public static void addIntegration(@NotNull final PlaceholderIntegration integration) {
integration.registerIntegration();
REGISTERED_INTEGRATIONS.add(integration);
}
/**
* Register a placeholder.
*
* @param expansion The {@link PlaceholderEntry} to register.
*/
public static void registerPlaceholder(@NotNull final PlaceholderEntry expansion) {
REGISTERED_PLACEHOLDERS.removeIf(placeholderEntry -> placeholderEntry.getIdentifier().equalsIgnoreCase(expansion.getIdentifier()));
REGISTERED_PLACEHOLDERS.add(expansion);
}
/**
* Get the result of a placeholder with respect to a player.
*
* @param player The player to get the result from.
* @param identifier The placeholder identifier.
* @return The value of the placeholder.
*/
public static String getResult(@Nullable final Player player,
@NotNull final String identifier) {
Optional<PlaceholderEntry> matching = REGISTERED_PLACEHOLDERS.stream().filter(expansion -> expansion.getIdentifier().equalsIgnoreCase(identifier)).findFirst();
if (!matching.isPresent()) {
return null;
}
PlaceholderEntry entry = matching.get();
if (player == null && entry.requiresPlayer()) {
return "";
}
return entry.getResult(player);
}
/**
* Translate all placeholders with respect to a player.
*
* @param text The text that may contain placeholders to translate.
* @param player The player to translate the placeholders with respect to.
* @return The text, translated.
*/
public static String translatePlaceholders(@NotNull final String text,
@Nullable final Player player) {
AtomicReference<String> translatedReference = new AtomicReference<>(text);
REGISTERED_INTEGRATIONS.forEach(placeholderIntegration -> translatedReference.set(placeholderIntegration.translate(translatedReference.get(), player)));
return translatedReference.get();
}
}

View File

@ -1,73 +0,0 @@
package com.willfp.eco.util.integrations.placeholder.plugins;
import com.willfp.eco.util.integrations.placeholder.PlaceholderIntegration;
import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PlaceholderIntegrationPAPI extends PlaceholderExpansion implements PlaceholderIntegration {
/**
* The linked plugin.
*/
private final AbstractEcoPlugin plugin;
/**
* Create a new PlaceholderAPI integration.
*
* @param plugin The plugin to manage placeholders for.
*/
public PlaceholderIntegrationPAPI(@NotNull final AbstractEcoPlugin plugin) {
this.plugin = plugin;
}
@Override
public boolean persist() {
return true;
}
@Override
public boolean canRegister() {
return true;
}
@Override
public @NotNull String getAuthor() {
return "Auxilor";
}
@Override
public @NotNull String getIdentifier() {
return plugin.getDescription().getName().toLowerCase();
}
@Override
public @NotNull String getVersion() {
return plugin.getDescription().getVersion();
}
@Override
public String onPlaceholderRequest(@Nullable final Player player,
@NotNull final String identifier) {
return PlaceholderManager.getResult(player, identifier);
}
@Override
public void registerIntegration() {
this.register();
}
@Override
public String getPluginName() {
return "PlaceholderAPI";
}
@Override
public String translate(@NotNull final String text,
@Nullable final Player player) {
return PlaceholderAPI.setPlaceholders(player, text);
}
}

View File

@ -1,11 +0,0 @@
package com.willfp.eco.util.interfaces;
public interface EcoRunnable extends Runnable {
/**
* The EcoRunnable interface is generally used for repeating tasks.
* This method is to retrieve the ticks between repetitions.
*
* @return The ticks between repetitions.
*/
long getTime();
}

View File

@ -1,8 +0,0 @@
package com.willfp.eco.util.interfaces;
public interface Registerable {
/**
* Register an object with its respective registry.
*/
void register();
}

View File

@ -1,23 +0,0 @@
package com.willfp.eco.util.internal;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.AccessLevel;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
public abstract class PluginDependent {
/**
* The {@link AbstractEcoPlugin} that is stored.
*/
@Getter(AccessLevel.PROTECTED)
private final AbstractEcoPlugin plugin;
/**
* Pass an {@link AbstractEcoPlugin} in order to interface with it.
*
* @param plugin The plugin to manage.
*/
protected PluginDependent(@NotNull final AbstractEcoPlugin plugin) {
this.plugin = plugin;
}
}

View File

@ -1,12 +0,0 @@
package com.willfp.eco.util.internal;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@ApiStatus.Internal
public abstract class PluginDependentFactory extends PluginDependent {
protected PluginDependentFactory(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
}

View File

@ -1,94 +0,0 @@
package com.willfp.eco.util.optional;
import com.willfp.eco.util.ClassUtils;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
public class Prerequisite {
/**
* All existing prerequisites are registered on creation.
*/
private static final List<Prerequisite> VALUES = new ArrayList<>();
/**
* Requires the server to be running minecraft version 1.16 or higher.
*/
public static final Prerequisite MINIMUM_1_16 = new Prerequisite(
() -> !Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3].contains("15"),
"Requires minimum server version of 1.16"
);
/**
* Requires the server to be running an implementation of paper.
*/
public static final Prerequisite HAS_PAPER = new Prerequisite(
() -> ClassUtils.exists("com.destroystokyo.paper.event.player.PlayerElytraBoostEvent"),
"Requires server to be running paper (or a fork)"
);
/**
* If the necessary prerequisite condition has been met.
*/
@Getter
private boolean isMet;
/**
* Retrieve if the necessary prerequisite condition is met.
*/
private final Supplier<Boolean> isMetSupplier;
/**
* The description of the requirements of the prerequisite.
*/
@Getter
private final String description;
/**
* Create a prerequisite.
*
* @param isMetSupplier An {@link Supplier<Boolean>} that returns if the prerequisite is met
* @param description The description of the prerequisite, shown to the user if it isn't
*/
public Prerequisite(@NotNull final Supplier<Boolean> isMetSupplier,
@NotNull final String description) {
this.isMetSupplier = isMetSupplier;
this.isMet = isMetSupplier.get();
this.description = description;
VALUES.add(this);
}
/**
* Refresh the condition set in the supplier, updates {@link this#isMet}.
*/
private void refresh() {
this.isMet = this.isMetSupplier.get();
}
/**
* Update all prerequisites' {@link Prerequisite#isMet}.
*/
public static void update() {
VALUES.forEach(Prerequisite::refresh);
}
/**
* Check if all prerequisites in array are met.
*
* @param prerequisites A primitive array of prerequisites to check.
* @return If all the prerequisites are met.
*/
public static boolean areMet(@NotNull final Prerequisite[] prerequisites) {
update();
return Arrays.stream(prerequisites).allMatch(Prerequisite::isMet);
}
static {
update();
}
}

View File

@ -1,409 +0,0 @@
package com.willfp.eco.util.plugin;
import com.willfp.eco.util.arrows.ArrowDataListener;
import com.willfp.eco.util.bukkit.events.EcoEventManager;
import com.willfp.eco.util.bukkit.events.EventManager;
import com.willfp.eco.util.bukkit.keys.NamespacedKeyFactory;
import com.willfp.eco.util.bukkit.logging.EcoLogger;
import com.willfp.eco.util.bukkit.logging.Logger;
import com.willfp.eco.util.bukkit.meta.MetadataValueFactory;
import com.willfp.eco.util.bukkit.scheduling.EcoScheduler;
import com.willfp.eco.util.bukkit.scheduling.RunnableFactory;
import com.willfp.eco.util.bukkit.scheduling.Scheduler;
import com.willfp.eco.util.command.AbstractCommand;
import com.willfp.eco.util.config.Configs;
import com.willfp.eco.util.config.updating.ConfigHandler;
import com.willfp.eco.util.drops.internal.DropManager;
import com.willfp.eco.util.drops.internal.FastCollatedDropQueue;
import com.willfp.eco.util.events.armorequip.ArmorListener;
import com.willfp.eco.util.events.armorequip.DispenserArmorListener;
import com.willfp.eco.util.events.entitydeathbyentity.EntityDeathByEntityListeners;
import com.willfp.eco.util.events.naturalexpgainevent.NaturalExpGainListeners;
import com.willfp.eco.util.extensions.loader.EcoExtensionLoader;
import com.willfp.eco.util.extensions.loader.ExtensionLoader;
import com.willfp.eco.util.integrations.IntegrationLoader;
import com.willfp.eco.util.integrations.anticheat.AnticheatManager;
import com.willfp.eco.util.integrations.anticheat.plugins.AnticheatAAC;
import com.willfp.eco.util.integrations.anticheat.plugins.AnticheatMatrix;
import com.willfp.eco.util.integrations.anticheat.plugins.AnticheatNCP;
import com.willfp.eco.util.integrations.anticheat.plugins.AnticheatSpartan;
import com.willfp.eco.util.integrations.antigrief.AntigriefManager;
import com.willfp.eco.util.integrations.antigrief.plugins.AntigriefFactionsUUID;
import com.willfp.eco.util.integrations.antigrief.plugins.AntigriefGriefPrevention;
import com.willfp.eco.util.integrations.antigrief.plugins.AntigriefKingdoms;
import com.willfp.eco.util.integrations.antigrief.plugins.AntigriefLands;
import com.willfp.eco.util.integrations.antigrief.plugins.AntigriefTowny;
import com.willfp.eco.util.integrations.antigrief.plugins.AntigriefWorldGuard;
import com.willfp.eco.util.integrations.placeholder.PlaceholderManager;
import com.willfp.eco.util.integrations.placeholder.plugins.PlaceholderIntegrationPAPI;
import com.willfp.eco.util.optional.Prerequisite;
import com.willfp.eco.util.protocollib.AbstractPacketAdapter;
import com.willfp.eco.util.updater.UpdateChecker;
import lombok.Getter;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.event.Listener;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public abstract class AbstractEcoPlugin extends JavaPlugin {
/**
* The instance of the plugin.
*/
@Getter
private static AbstractEcoPlugin instance;
/**
* The name of the plugin.
*/
@Getter
private final String pluginName;
/**
* The spigot resource ID of the plugin.
*/
@Getter
private final int resourceId;
/**
* The bStats resource ID of the plugin.
*/
@Getter
private final int bStatsId;
/**
* The package where proxy implementations are.
*/
@Getter
private final String proxyPackage;
/**
* Set of external plugin integrations.
*/
private final List<IntegrationLoader> integrationLoaders = new ArrayList<>();
/**
* Set of classes to be processed on config update.
*/
private final List<Class<?>> updatableClasses = new ArrayList<>();
/**
* The internal plugin logger.
*/
@Getter
private final Logger log;
/**
* The internal plugin scheduler.
*/
@Getter
private final Scheduler scheduler;
/**
* The internal plugin Event Manager.
*/
@Getter
private final EventManager eventManager;
/**
* The internal factory to produce {@link org.bukkit.NamespacedKey}s.
*/
@Getter
private final NamespacedKeyFactory namespacedKeyFactory;
/**
* The internal factory to produce {@link org.bukkit.metadata.FixedMetadataValue}s.
*/
@Getter
private final MetadataValueFactory metadataValueFactory;
/**
* The internal factory to produce {@link com.willfp.eco.util.bukkit.scheduling.EcoBukkitRunnable}s.
*/
@Getter
private final RunnableFactory runnableFactory;
/**
* The loader for all plugin extensions.
*
* @see com.willfp.eco.util.extensions.Extension
*/
@Getter
private final ExtensionLoader extensionLoader;
/**
* The handler class for updatable classes.
*/
@Getter
private final ConfigHandler configHandler;
/**
* If the server is running an outdated version of the plugin.
*/
@Getter
private boolean outdated = false;
/**
* Create a new plugin.
*
* @param pluginName The name of the plugin.
* @param resourceId The spigot resource ID for the plugin.
* @param bStatsId The bStats resource ID for the plugin.
* @param proxyPackage The package where proxy implementations are stored.
*/
protected AbstractEcoPlugin(@NotNull final String pluginName,
final int resourceId,
final int bStatsId,
@NotNull final String proxyPackage) {
this.pluginName = pluginName;
this.resourceId = resourceId;
this.bStatsId = bStatsId;
this.proxyPackage = proxyPackage;
this.log = new EcoLogger(this);
this.scheduler = new EcoScheduler(this);
this.eventManager = new EcoEventManager(this);
this.namespacedKeyFactory = new NamespacedKeyFactory(this);
this.metadataValueFactory = new MetadataValueFactory(this);
this.runnableFactory = new RunnableFactory(this);
this.extensionLoader = new EcoExtensionLoader(this);
this.configHandler = new ConfigHandler(this);
}
/**
* Default code to be executed on plugin enable.
*/
@Override
public final void onEnable() {
super.onLoad();
this.getLog().info("==========================================");
this.getLog().info("");
this.getLog().info("Loading &a" + this.pluginName);
this.getLog().info("Made by &aAuxilor&f - willfp.com");
this.getLog().info("");
this.getLog().info("==========================================");
this.getEventManager().registerListener(new ArrowDataListener(this));
this.getEventManager().registerListener(new NaturalExpGainListeners());
this.getEventManager().registerListener(new ArmorListener());
this.getEventManager().registerListener(new DispenserArmorListener());
this.getEventManager().registerListener(new EntityDeathByEntityListeners(this));
new FastCollatedDropQueue.CollatedRunnable(this);
new UpdateChecker(this).getVersion(version -> {
DefaultArtifactVersion currentVersion = new DefaultArtifactVersion(this.getDescription().getVersion());
DefaultArtifactVersion mostRecentVersion = new DefaultArtifactVersion(version);
if (!(currentVersion.compareTo(mostRecentVersion) > 0 || currentVersion.equals(mostRecentVersion))) {
this.outdated = true;
this.getScheduler().runTimer(() -> {
this.getLog().info("&c " + this.pluginName + " is out of date! (Version " + this.getDescription().getVersion() + ")");
this.getLog().info("&cThe newest version is &f" + version);
this.getLog().info("&cDownload the new version!");
}, 0, 864000);
}
});
new Metrics(this, this.bStatsId);
Set<String> enabledPlugins = Arrays.stream(Bukkit.getPluginManager().getPlugins()).map(Plugin::getName).collect(Collectors.toSet());
this.getDefaultIntegrations().forEach((integrationLoader -> {
StringBuilder infoBuilder = new StringBuilder();
infoBuilder.append(integrationLoader.getPluginName()).append(": ");
if (enabledPlugins.contains(integrationLoader.getPluginName())) {
integrationLoader.load();
infoBuilder.append("&aENABLED");
} else {
infoBuilder.append("&9DISABLED");
}
this.getLog().info(infoBuilder.toString());
}));
this.getLog().info("");
Prerequisite.update();
this.getPacketAdapters().forEach(abstractPacketAdapter -> {
if (!abstractPacketAdapter.isPostLoad()) {
abstractPacketAdapter.register();
}
});
updatableClasses.add(Configs.class);
updatableClasses.add(DropManager.class);
updatableClasses.addAll(this.getUpdatableClasses());
this.getListeners().forEach(listener -> this.getEventManager().registerListener(listener));
this.getCommands().forEach(AbstractCommand::register);
this.getScheduler().runLater(this::afterLoad, 1);
this.updatableClasses.forEach(clazz -> this.getConfigHandler().registerUpdatableClass(clazz));
this.enable();
}
/**
* Default code to be executed on plugin disable.
*/
@Override
public final void onDisable() {
super.onDisable();
this.getEventManager().unregisterAllListeners();
this.getScheduler().cancelAll();
this.disable();
}
/**
* Default code to be executed on plugin load.
*/
@Override
public final void onLoad() {
super.onLoad();
instance = this;
this.load();
}
/**
* Default code to be executed after the server is up.
*/
public final void afterLoad() {
this.getPacketAdapters().forEach(abstractPacketAdapter -> {
if (abstractPacketAdapter.isPostLoad()) {
abstractPacketAdapter.register();
}
});
if (!Prerequisite.HAS_PAPER.isMet()) {
this.getLog().error("");
this.getLog().error("----------------------------");
this.getLog().error("");
this.getLog().error("You don't seem to be running paper!");
this.getLog().error("Paper is strongly recommended for all servers,");
this.getLog().error("and some things may not function properly without it");
this.getLog().error("Download Paper from &fhttps://papermc.io");
this.getLog().error("");
this.getLog().error("----------------------------");
this.getLog().error("");
}
this.postLoad();
this.reload();
this.getLog().info("Loaded &a" + this.pluginName);
}
/**
* Default code to be executed on plugin reload.
*/
public final void reload() {
this.getConfigHandler().callUpdate();
this.getScheduler().cancelAll();
new FastCollatedDropQueue.CollatedRunnable(this);
this.onReload();
}
/**
* Default integrations that exist within {@link AbstractEcoPlugin}.
*
* @return The default integrations.
*/
public final List<IntegrationLoader> getDefaultIntegrations() {
integrationLoaders.add(new IntegrationLoader("PlaceholderAPI", () -> PlaceholderManager.addIntegration(new PlaceholderIntegrationPAPI(this))));
// AntiGrief
integrationLoaders.add(new IntegrationLoader("WorldGuard", () -> AntigriefManager.register(new AntigriefWorldGuard())));
integrationLoaders.add(new IntegrationLoader("GriefPrevention", () -> AntigriefManager.register(new AntigriefGriefPrevention())));
integrationLoaders.add(new IntegrationLoader("FactionsUUID", () -> AntigriefManager.register(new AntigriefFactionsUUID())));
integrationLoaders.add(new IntegrationLoader("Towny", () -> AntigriefManager.register(new AntigriefTowny())));
integrationLoaders.add(new IntegrationLoader("Lands", () -> AntigriefManager.register(new AntigriefLands(this))));
integrationLoaders.add(new IntegrationLoader("Kingdoms", () -> AntigriefManager.register(new AntigriefKingdoms())));
// Anticheat
integrationLoaders.add(new IntegrationLoader("AAC5", () -> AnticheatManager.register(new AnticheatAAC())));
integrationLoaders.add(new IntegrationLoader("Matrix", () -> AnticheatManager.register(new AnticheatMatrix())));
integrationLoaders.add(new IntegrationLoader("NoCheatPlus", () -> AnticheatManager.register(new AnticheatNCP())));
integrationLoaders.add(new IntegrationLoader("Spartan", () -> AnticheatManager.register(new AnticheatSpartan())));
integrationLoaders.addAll(this.getIntegrationLoaders());
return integrationLoaders;
}
/**
* The plugin-specific code to be executed on enable.
*/
public abstract void enable();
/**
* The plugin-specific code to be executed on disable.
*/
public abstract void disable();
/**
* The plugin-specific code to be executed on load.
*/
public abstract void load();
/**
* The plugin-specific code to be executed on reload.
*/
public abstract void onReload();
/**
* The plugin-specific code to be executed after the server is up.
*/
public abstract void postLoad();
/**
* The plugin-specific integrations to be tested and loaded.
*
* @return A list of integrations.
*/
public abstract List<IntegrationLoader> getIntegrationLoaders();
/**
* The command to be registered.
*
* @return A list of commands.
*/
public abstract List<AbstractCommand> getCommands();
/**
* ProtocolLib packet adapters to be registered.
* <p>
* If the plugin does not require ProtocolLib this can be left empty.
*
* @return A list of packet adapters.
*/
public abstract List<AbstractPacketAdapter> getPacketAdapters();
/**
* All listeners to be registered.
*
* @return A list of all listeners.
*/
public abstract List<Listener> getListeners();
/**
* All updatable classes.
*
* @return A list of all updatable classes.
*/
public abstract List<Class<?>> getUpdatableClasses();
}

View File

@ -1,121 +0,0 @@
package com.willfp.eco.util.protocollib;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public abstract class AbstractPacketAdapter extends PacketAdapter {
/**
* The packet type to listen for.
*/
private final PacketType type;
/**
* Whether the packet adapter should be registered after the server has loaded.
* <p>
* Useful for monitor priority adapters that <b>must</b> be ran last.
*/
@Getter
private final boolean postLoad;
/**
* Create a new packet adapter for a specified plugin and type.
*
* @param plugin The plugin that ProtocolLib should mark as the owner.
* @param type The {@link PacketType} to listen for.
* @param priority The priority at which the adapter should be ran on packet send/receive.
* @param postLoad If the packet adapter should be registered after the server has loaded.
*/
protected AbstractPacketAdapter(@NotNull final AbstractEcoPlugin plugin,
@NotNull final PacketType type,
@NotNull final ListenerPriority priority,
final boolean postLoad) {
super(plugin, priority, Collections.singletonList(type));
this.type = type;
this.postLoad = postLoad;
}
/**
* Create a new packet adapter for a specified plugin and type.
*
* @param plugin The plugin that ProtocolLib should mark as the owner.
* @param type The {@link PacketType} to listen for.
* @param postLoad If the packet adapter should be registered after the server has loaded.
*/
protected AbstractPacketAdapter(@NotNull final AbstractEcoPlugin plugin,
@NotNull final PacketType type,
final boolean postLoad) {
this(plugin, type, ListenerPriority.NORMAL, postLoad);
}
/**
* The code that should be executed once the packet has been received.
*
* @param packet The packet.
*/
public void onReceive(@NotNull final PacketContainer packet) {
// Empty rather than abstract as implementations don't need both
}
/**
* THe code that should be executed once the packet has been sent.
*
* @param packet The packet.
*/
public void onSend(@NotNull final PacketContainer packet) {
// Empty rather than abstract as implementations don't need both
}
/**
* Boilerplate to assert that the packet is of the specified type.
*
* @param event The ProtocolLib event.
*/
@Override
public final void onPacketReceiving(final PacketEvent event) {
if (event.getPacket() == null) {
return;
}
if (!event.getPacket().getType().equals(type)) {
return;
}
onReceive(event.getPacket());
}
/**
* Boilerplate to assert that the packet is of the specified type.
*
* @param event The ProtocolLib event.
*/
@Override
public final void onPacketSending(final PacketEvent event) {
if (event.getPacket() == null) {
return;
}
if (!event.getPacket().getType().equals(type)) {
return;
}
onSend(event.getPacket());
}
/**
* Register the packet adapter with ProtocolLib.
*/
public final void register() {
if (!ProtocolLibrary.getProtocolManager().getPacketListeners().contains(this)) {
ProtocolLibrary.getProtocolManager().addPacketListener(this);
}
}
}

View File

@ -1,5 +0,0 @@
package com.willfp.eco.util.proxy;
public interface AbstractProxy {
}

View File

@ -1,12 +0,0 @@
package com.willfp.eco.util.proxy;
import lombok.experimental.UtilityClass;
import org.bukkit.Bukkit;
@UtilityClass
public class ProxyConstants {
/**
* The NMS version that the server is running on.
*/
public static final String NMS_VERSION = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
}

View File

@ -1,72 +0,0 @@
package com.willfp.eco.util.proxy;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.IdentityHashMap;
import java.util.Map;
public class ProxyFactory<T extends AbstractProxy> extends PluginDependent {
/**
* Cached proxy implementations in order to not perform expensive reflective class-finding.
*/
private static final Map<Class<? extends AbstractProxy>, AbstractProxy> CACHE = new IdentityHashMap<>();
/**
* The class of the proxy interface.
*/
private final Class<T> proxyClass;
/**
* Create a new Proxy Factory for a specific type.
*
* @param plugin The plugin to create proxies for.
* @param proxyClass The class of the proxy interface.
*/
public ProxyFactory(@NotNull final AbstractEcoPlugin plugin,
@NotNull final Class<T> proxyClass) {
super(plugin);
this.proxyClass = proxyClass;
}
/**
* Get the implementation of a proxy.
*
* @return The proxy implementation.
*/
public @NotNull T getProxy() {
try {
T cachedProxy = attemptCache();
if (cachedProxy != null) {
return cachedProxy;
}
String className = this.getPlugin().getProxyPackage() + "." + ProxyConstants.NMS_VERSION + "." + proxyClass.getSimpleName().replace("Proxy", "");
final Class<?> class2 = Class.forName(className);
Object instance = class2.getConstructor().newInstance();
if (proxyClass.isAssignableFrom(class2) && proxyClass.isInstance(instance)) {
T proxy = proxyClass.cast(instance);
CACHE.put(proxyClass, proxy);
return proxy;
}
} catch (Exception e) {
// If not returned, then throw error
}
throw new UnsupportedVersionException("You're running an unsupported server version: " + ProxyConstants.NMS_VERSION);
}
private T attemptCache() {
Object proxy = CACHE.get(proxyClass);
if (proxy == null) {
return null;
}
if (proxyClass.isInstance(proxy)) {
return proxyClass.cast(proxy);
}
return null;
}
}

View File

@ -1,14 +0,0 @@
package com.willfp.eco.util.proxy;
import org.jetbrains.annotations.NotNull;
public class UnsupportedVersionException extends RuntimeException {
/**
* Thrown if the server is running an unsupported NMS version.
*
* @param message The message to send.
*/
public UnsupportedVersionException(@NotNull final String message) {
super(message);
}
}

View File

@ -1,37 +0,0 @@
package com.willfp.eco.util.tuplets;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.jetbrains.annotations.Nullable;
@ToString
public class Pair<A, B> {
/**
* The first value in the pair.
*/
@Getter
@Setter
@Nullable
private A first;
/**
* The second value in the pair.
*/
@Getter
@Setter
@Nullable
private B second;
/**
* Create a pair of values.
*
* @param first The first item in the pair.
* @param second The second item in the pair.
*/
public Pair(@Nullable final A first,
@Nullable final B second) {
this.first = first;
this.second = second;
}
}

View File

@ -1,48 +0,0 @@
package com.willfp.eco.util.tuplets;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.jetbrains.annotations.Nullable;
@ToString
public class Triplet<A, B, C> {
/**
* The first item in the triplet.
*/
@Getter
@Setter
@Nullable
private A first;
/**
* The second item in the triplet.
*/
@Getter
@Setter
@Nullable
private B second;
/**
* The third item in the triplet.
*/
@Getter
@Setter
@Nullable
private C third;
/**
* Create a triplet.
*
* @param first The first item in the triplet.
* @param second The second item in the triplet.
* @param third The third item in the triplet.
*/
public Triplet(@Nullable final A first,
@Nullable final B second,
@Nullable final C third) {
this.first = first;
this.second = second;
this.third = third;
}
}

View File

@ -1,42 +0,0 @@
package com.willfp.eco.util.updater;
import com.willfp.eco.util.internal.PluginDependent;
import com.willfp.eco.util.plugin.AbstractEcoPlugin;
import org.bukkit.util.Consumer;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Scanner;
public class UpdateChecker extends PluginDependent {
/**
* Create an update checker for the specified spigot resource id.
*
* @param plugin The plugin to check.
*/
public UpdateChecker(@NotNull final AbstractEcoPlugin plugin) {
super(plugin);
}
/**
* Get the latest version of the plugin.
*
* @param consumer The process to run after checking.
*/
public void getVersion(@NotNull final Consumer<? super String> consumer) {
this.getPlugin().getScheduler().runAsync(() -> {
try {
InputStream inputStream = new URL("https://api.spigotmc.org/legacy/update.php?resource=" + this.getPlugin().getResourceId()).openStream();
Scanner scanner = new Scanner(inputStream);
if (scanner.hasNext()) {
consumer.accept(scanner.next());
}
} catch (IOException e) {
this.getPlugin().getLogger().warning("Failed to check for updates: " + e.getMessage());
}
});
}
}

View File

@ -1,7 +1,5 @@
rootProject.name = 'parent'
include ':eco-util'
// Core
include ':eco-core'
include ':eco-core:core-nms'