From d67bbbf4b484d28c33c069fb7e04ccd7a2eeb810 Mon Sep 17 00:00:00 2001 From: jascotty2 Date: Fri, 23 Aug 2019 09:07:48 -0500 Subject: [PATCH] housekeeping, fix vault eco without eco, add WG5 compat, add some particles compat --- .../java/com/songoda/core/PluginInfo.java | 14 +- .../com/songoda/core/PluginInfoModule.java | 7 + .../java/com/songoda/core/SongodaCore.java | 3 +- .../ChatPrompt.java} | 53 ++-- .../compatibility/LegacyParticleEffects.java | 249 ++++++++++++++++++ .../compatibility/LegacyPotionEffects.java | 49 ++++ .../compatibility/ParticleHandler.java | 66 +++++ .../core/library/economy/EconomyManager.java | 8 +- .../library/economy/economies/Economy.java | 6 + .../economies/PlayerPointsEconomy.java | 5 + .../economy/economies/ReserveEconomy.java | 5 + .../economy/economies/VaultEconomy.java | 22 +- .../hooks/hooks/WorldGuardFlagHandler.java | 70 +++-- .../songoda/core/library/locale/Locale.java | 19 +- .../songoda/core/library/locale/Message.java | 8 +- .../songoda/core/listeners/LoginListener.java | 27 -- .../java/com/songoda/core/modules/Module.java | 9 - .../core/modules/common/LocaleModule.java | 4 +- 18 files changed, 520 insertions(+), 104 deletions(-) create mode 100644 src/main/java/com/songoda/core/PluginInfoModule.java rename src/main/java/com/songoda/core/{utils/AbstractChatConfirm.java => input/ChatPrompt.java} (61%) create mode 100644 src/main/java/com/songoda/core/library/compatibility/LegacyParticleEffects.java create mode 100644 src/main/java/com/songoda/core/library/compatibility/LegacyPotionEffects.java create mode 100644 src/main/java/com/songoda/core/library/compatibility/ParticleHandler.java delete mode 100644 src/main/java/com/songoda/core/listeners/LoginListener.java delete mode 100644 src/main/java/com/songoda/core/modules/Module.java diff --git a/src/main/java/com/songoda/core/PluginInfo.java b/src/main/java/com/songoda/core/PluginInfo.java index be25549a..29432a0f 100644 --- a/src/main/java/com/songoda/core/PluginInfo.java +++ b/src/main/java/com/songoda/core/PluginInfo.java @@ -1,17 +1,17 @@ package com.songoda.core; -import com.songoda.core.modules.Module; import org.bukkit.plugin.java.JavaPlugin; import org.json.simple.JSONObject; import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class PluginInfo { - private JavaPlugin javaPlugin; - private int songodaId; - private List modules = new ArrayList<>(); + private final JavaPlugin javaPlugin; + private final int songodaId; + private final List modules = new ArrayList<>(); private String latestVersion; private String notification; private String changeLog; @@ -63,13 +63,13 @@ public class PluginInfo { this.json = json; } - public Module addModule(Module module) { + public PluginInfoModule addModule(PluginInfoModule module) { modules.add(module); return module; } - public List getModules() { - return new ArrayList<>(modules); + public List getModules() { + return Collections.unmodifiableList(modules); } public JavaPlugin getJavaPlugin() { diff --git a/src/main/java/com/songoda/core/PluginInfoModule.java b/src/main/java/com/songoda/core/PluginInfoModule.java new file mode 100644 index 00000000..25eef020 --- /dev/null +++ b/src/main/java/com/songoda/core/PluginInfoModule.java @@ -0,0 +1,7 @@ +package com.songoda.core; + +public interface PluginInfoModule { + + void run(PluginInfo plugin); + +} diff --git a/src/main/java/com/songoda/core/SongodaCore.java b/src/main/java/com/songoda/core/SongodaCore.java index 8520795b..ca1c0e29 100644 --- a/src/main/java/com/songoda/core/SongodaCore.java +++ b/src/main/java/com/songoda/core/SongodaCore.java @@ -1,7 +1,6 @@ package com.songoda.core; import com.songoda.core.library.commands.CommandManager; -import com.songoda.core.modules.Module; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -142,7 +141,7 @@ public class SongodaCore { plugin.setJson(json); - for (Module module : plugin.getModules()) { + for (PluginInfoModule module : plugin.getModules()) { module.run(plugin); } } catch (IOException e) { diff --git a/src/main/java/com/songoda/core/utils/AbstractChatConfirm.java b/src/main/java/com/songoda/core/input/ChatPrompt.java similarity index 61% rename from src/main/java/com/songoda/core/utils/AbstractChatConfirm.java rename to src/main/java/com/songoda/core/input/ChatPrompt.java index 5360e8b4..29d4fa54 100644 --- a/src/main/java/com/songoda/core/utils/AbstractChatConfirm.java +++ b/src/main/java/com/songoda/core/input/ChatPrompt.java @@ -1,36 +1,46 @@ -package com.songoda.core.utils; +package com.songoda.core.input; -import com.songoda.core.SongodaCore; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; import org.bukkit.event.player.AsyncPlayerChatEvent; -import org.bukkit.plugin.java.JavaPlugin; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.bukkit.plugin.Plugin; -public class AbstractChatConfirm implements Listener { +public class ChatPrompt implements Listener { private static final List registered = new ArrayList<>(); - private final Player player; private final ChatConfirmHandler handler; - private OnClose onClose = null; private Listener listener; - public AbstractChatConfirm(Player player, ChatConfirmHandler hander) { - this.player = player; + private ChatPrompt(Player player, ChatConfirmHandler hander) { this.handler = hander; - player.closeInventory(); - initializeListeners(SongodaCore.getHijackedPlugin()); registered.add(player.getUniqueId()); } + public static ChatPrompt showPrompt(Plugin plugin, Player player, ChatConfirmHandler hander) { + ChatPrompt prompt = new ChatPrompt(player, hander); + prompt.startListener(plugin); + player.closeInventory(); + return prompt; + } + + public static ChatPrompt showPrompt(Plugin plugin, Player player, String message, ChatConfirmHandler hander) { + ChatPrompt prompt = new ChatPrompt(player, hander); + prompt.startListener(plugin); + player.closeInventory(); + if (message != null) + player.sendMessage(message); + return prompt; + } + public static boolean isRegistered(Player player) { return registered.contains(player.getUniqueId()); } @@ -39,15 +49,19 @@ public class AbstractChatConfirm implements Listener { return registered.remove(player.getUniqueId()); } - public void initializeListeners(JavaPlugin plugin) { + public ChatPrompt setOnClose(OnClose onClose) { + this.onClose = onClose; + return this; + } + private void startListener(Plugin plugin) { this.listener = new Listener() { @EventHandler public void onChat(AsyncPlayerChatEvent event) { Player player = event.getPlayer(); - if (!AbstractChatConfirm.isRegistered(player)) return; + if (!ChatPrompt.isRegistered(player)) return; - AbstractChatConfirm.unregister(player); + ChatPrompt.unregister(player); event.setCancelled(true); ChatConfirmEvent chatConfirmEvent = new ChatConfirmEvent(player, event.getMessage()); @@ -61,23 +75,18 @@ public class AbstractChatConfirm implements Listener { } }; - - Bukkit.getPluginManager().registerEvents(listener, SongodaCore.getHijackedPlugin()); + Bukkit.getPluginManager().registerEvents(listener, plugin); } - public void setOnClose(OnClose onClose) { - this.onClose = onClose; - } - - public interface ChatConfirmHandler { + public static interface ChatConfirmHandler { void onChat(ChatConfirmEvent event); } - public interface OnClose { + public static interface OnClose { void onClose(); } - public class ChatConfirmEvent { + public static class ChatConfirmEvent { private final Player player; private final String message; diff --git a/src/main/java/com/songoda/core/library/compatibility/LegacyParticleEffects.java b/src/main/java/com/songoda/core/library/compatibility/LegacyParticleEffects.java new file mode 100644 index 00000000..de710cb3 --- /dev/null +++ b/src/main/java/com/songoda/core/library/compatibility/LegacyParticleEffects.java @@ -0,0 +1,249 @@ +package com.songoda.core.library.compatibility; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +public class LegacyParticleEffects { + + public static enum Type { + + EXPLOSION_NORMAL("explode"), + EXPLOSION_LARGE("largeexplode"), + EXPLOSION_HUGE("hugeexplosion"), + FIREWORKS_SPARK("fireworksSpark"), + WATER_BUBBLE("bubble"), + WATER_SPLASH("splash"), + WATER_WAKE("wake", ServerVersion.V1_8), + SUSPENDED("suspended"), + SUSPENDED_DEPTH("depthsuspend"), + CRIT("crit"), + CRIT_MAGIC("magicCrit"), + SMOKE_NORMAL("smoke"), + SMOKE_LARGE("largesmoke"), + SPELL("spell"), + SPELL_INSTANT("instantSpell"), + SPELL_MOB("mobSpell"), + SPELL_MOB_AMBIENT("mobSpellAmbient"), + SPELL_WITCH("witchMagic"), + DRIP_WATER("dripWater"), + DRIP_LAVA("dripLava"), + VILLAGER_ANGRY("angryVillager"), + VILLAGER_HAPPY("happyVillager"), + TOWN_AURA("townaura"), + NOTE("note"), + PORTAL("portal"), + ENCHANTMENT_TABLE("enchantmenttable"), + FLAME("flame"), + LAVA("lava"), + FOOTSTEP("footstep"), + CLOUD("cloud"), + REDSTONE("reddust"), + SNOWBALL("snowballpoof"), + SNOW_SHOVEL("snowshovel"), + SLIME("slime"), + HEART("heart"), + BARRIER("barrier", ServerVersion.V1_8), + /** + * Used when a block is broken + */ + ITEM_CRACK("iconcrack_"), + BLOCK_CRACK("blockcrack_", ServerVersion.V1_8), + BLOCK_DUST("blockdust_", ServerVersion.V1_8), + WATER_DROP("droplet", ServerVersion.V1_8), + ITEM_TAKE("take", ServerVersion.V1_8), + MOB_APPEARANCE("mobappearance", ServerVersion.V1_8), + TOOL_BREAK("tilecrack_", ServerVersion.UNKNOWN, ServerVersion.V1_7); + + public final String name; + public final ServerVersion minVersion; + public final ServerVersion maxVersion; + + private Type(String name) { + this.name = name; + this.minVersion = ServerVersion.V1_7; + this.maxVersion = null; + } + + private Type(String name, ServerVersion minVersion) { + this.name = name; + this.minVersion = minVersion; + this.maxVersion = null; + } + + private Type(String name, ServerVersion minVersion, ServerVersion maxVersion) { + this.name = name; + this.minVersion = minVersion; + this.maxVersion = maxVersion; + } + + public static Type getById(String id) { + for (Type t : Type.values()) { + if (t.name.equalsIgnoreCase(id) || t.name().equalsIgnoreCase(id)) { + return t; + } + } + return null; + } + } + + private static final String version = getNMSVersion(); + private static boolean enabled = true; + private static Class mc_packetPlayOutWorldParticlesClazz; + private static Class cb_craftPlayerClazz; + private static Method cb_craftPlayer_getHandle; + private static Class mc_entityPlayerClazz; + private static Class mc_playerConnectionClazz; + private static Field mc_entityPlayer_playerConnection; + private static Class mc_PacketInterface; + private static Method mc_playerConnection_sendPacket; + private static Class mc_EnumParticle; + private static Method mc_EnumParticle_valueOf; + + static { + try { + // lower versions use "Packet63WorldParticles" + if (!version.startsWith("v1_7") && !version.startsWith("v1_8")) { + mc_packetPlayOutWorldParticlesClazz = Class.forName("net.minecraft.server." + version + ".Packet63WorldParticles"); + } else { + mc_packetPlayOutWorldParticlesClazz = Class.forName("net.minecraft.server." + version + ".PacketPlayOutWorldParticles"); + } + cb_craftPlayerClazz = Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftPlayer"); + cb_craftPlayer_getHandle = cb_craftPlayerClazz.getDeclaredMethod("getHandle"); + mc_entityPlayerClazz = Class.forName("net.minecraft.server." + version + ".EntityPlayer"); + mc_entityPlayer_playerConnection = mc_entityPlayerClazz.getDeclaredField("playerConnection"); + mc_playerConnectionClazz = Class.forName("net.minecraft.server." + version + ".PlayerConnection"); + mc_PacketInterface = Class.forName("net.minecraft.server." + version + ".Packet"); + mc_playerConnection_sendPacket = mc_playerConnectionClazz.getDeclaredMethod("sendPacket", mc_PacketInterface); + if (version.startsWith("v1_8")) { + // Aren't worrying about anything after 1.8 in this class here + mc_EnumParticle = Class.forName("net.minecraft.server." + version + ".EnumParticle"); + mc_EnumParticle_valueOf = mc_EnumParticle.getDeclaredMethod("valueOf", String.class); + } + } catch (Throwable ex) { + Logger.getAnonymousLogger().log(Level.WARNING, "Problem preparing particle packets (disabling further packets)", ex); + enabled = false; + } + } + + private static String getNMSVersion() { + String ver = Bukkit.getServer().getClass().getPackage().getName(); + return ver.substring(ver.lastIndexOf('.') + 1); + } + + public static void createParticle(Location l, Type e) { + createParticle(l, e, 0F, 0F, 0F, 1, 3, null); + } + + public static void createParticle(Location l, Type e, List localOnly) { + createParticle(l, e, 0F, 0F, 0F, 1, 3, localOnly); + } + + public static void createParticle(Location l, Type e, float effectSpeed, int amountOfParticles) { + createParticle(l, e, 0F, 0F, 0F, effectSpeed, amountOfParticles, null); + } + + /** + * + * @param l exact location to spawn the particle + * @param e particle effect type + * @param xx for notes, this is a value 0-1 for the color ([0-24]/24), for + * redstone this is the red value 0-1 ([0-255]/255). + * Otherwise this is the distance for particles to fly on the x-axis. + * @param yy for redstone this is the green value 0-1 ([0-255]/255) + * Otherwise this is the distance for particles to fly on the y-axis. + * @param zz for redstone this is the blue value 0-1 ([0-255]/255) + * Otherwise this is the distance for particles to fly on the z-axis. + * @param effectSpeed particle effect speed + * @param amountOfParticles extra particles to spawn (client-side) + * @param localOnly list of players to send the packets to, or null for all players + */ + public static void createParticle(Location l, Type e, float xx, float yy, float zz, float effectSpeed, int amountOfParticles, List localOnly) { + if (!enabled || e == null || effectSpeed < 0 || amountOfParticles < 0 + || !ServerVersion.isServerVersionAtLeast(e.minVersion) + || (e.maxVersion != null && !ServerVersion.isServerVersionBelow(e.maxVersion))) { + return; + } + final int rangeSquared = 256; // apparently there is no way to override this (unless to make smaller, of course) + // collect a list of players to send this packet to + List sendTo = new ArrayList(); + if (localOnly == null) { + for (Player p : l.getWorld().getPlayers()) { + if (p.getLocation().distanceSquared(l) <= rangeSquared) { + sendTo.add(p); + } + } + } else { + final World w = l.getWorld(); + for (Player p : localOnly) { + if (p.getWorld() == w && p.getLocation().distanceSquared(l) <= rangeSquared) { + sendTo.add(p); + } + } + } + if (sendTo.isEmpty()) { + return; + } + try { + // Make an instance of the packet! + Object sPacket = mc_packetPlayOutWorldParticlesClazz.newInstance(); + for (Field field : sPacket.getClass().getDeclaredFields()) { + // Set those fields we need to be accessible! + field.setAccessible(true); + final String fieldName = field.getName(); + // Set them to what we want! + if (fieldName.equals("a")) { + // we're just going to assume it's either 1.7 or 1.8 + if (version.startsWith("v1_8")) { + // 1.8 uses an Enum + field.set(sPacket, mc_EnumParticle_valueOf.invoke(null, e.name())); + } else { + field.set(sPacket, e.name); + } + } else if (fieldName.equals("b")) { + field.setFloat(sPacket, (float) l.getX()); // x + } else if (fieldName.equals("c")) { + field.setFloat(sPacket, (float) l.getY()); // y + } else if (fieldName.equals("d")) { + field.setFloat(sPacket, (float) l.getZ()); // z + } else if (fieldName.equals("e")) { + field.setFloat(sPacket, xx); // xOffset + } else if (fieldName.equals("f")) { + field.setFloat(sPacket, yy); // yOffset + } else if (fieldName.equals("g")) { + field.setFloat(sPacket, zz); // zOffset + } else if (fieldName.equals("h")) { + field.setFloat(sPacket, effectSpeed); + } else if (fieldName.equals("i")) { + field.setInt(sPacket, amountOfParticles); + } + /* + 1.8 also includes other data: + j = boolean, set if view distance is increased from 256 to 65536 + k = int[] for packet data (like block type for ITEM_CRACK) + */ + } + // send it on its way! + for (Player p : sendTo) { + sendPacket(sPacket, p); + } + } catch (Throwable ex) { + Logger.getAnonymousLogger().log(Level.WARNING, "Problem preparing a particle packet (disabling further packets)", ex); + enabled = false; + } + } + + private static void sendPacket(Object packet, Player to) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Object cbPlayer = cb_craftPlayer_getHandle.invoke(to); + Object mcConnection = mc_entityPlayer_playerConnection.get(cbPlayer); + mc_playerConnection_sendPacket.invoke(mcConnection, packet); + } +} diff --git a/src/main/java/com/songoda/core/library/compatibility/LegacyPotionEffects.java b/src/main/java/com/songoda/core/library/compatibility/LegacyPotionEffects.java new file mode 100644 index 00000000..6076e137 --- /dev/null +++ b/src/main/java/com/songoda/core/library/compatibility/LegacyPotionEffects.java @@ -0,0 +1,49 @@ +package com.songoda.core.library.compatibility; + +import java.util.HashMap; +import java.util.Random; +import org.bukkit.potion.PotionEffectType; + +public class LegacyPotionEffects { + + private LegacyPotionEffects() { + } + + protected final static Random rand = new Random(); + + private final static HashMap potionEffectNames = new HashMap() { + { + put(PotionEffectType.SPEED.getId(), "Speed"); + put(PotionEffectType.SLOW.getId(), "Slowness"); + put(PotionEffectType.FAST_DIGGING.getId(), "Haste"); + put(PotionEffectType.SLOW_DIGGING.getId(), "Mining Fatigue"); + put(PotionEffectType.INCREASE_DAMAGE.getId(), "Strength"); + put(PotionEffectType.WEAKNESS.getId(), "Weakness"); + put(PotionEffectType.HEAL.getId(), "Instant Health"); + put(PotionEffectType.HARM.getId(), "Instant Damage"); + put(PotionEffectType.JUMP.getId(), "Jump Boost"); + put(PotionEffectType.CONFUSION.getId(), "Nausea"); + put(PotionEffectType.REGENERATION.getId(), "Regeneration"); + put(PotionEffectType.DAMAGE_RESISTANCE.getId(), "Resistance"); + put(PotionEffectType.FIRE_RESISTANCE.getId(), "Fire Resistance"); + put(PotionEffectType.WATER_BREATHING.getId(), "Water Breathing"); + put(PotionEffectType.INVISIBILITY.getId(), "Invisibility"); + put(PotionEffectType.BLINDNESS.getId(), "Blindness"); + put(PotionEffectType.NIGHT_VISION.getId(), "Night Vision"); + put(PotionEffectType.HUNGER.getId(), "Hunger"); + put(PotionEffectType.POISON.getId(), "Poison"); + put(PotionEffectType.WITHER.getId(), "Wither"); + put(PotionEffectType.HEALTH_BOOST.getId(), "Health Boost"); + put(PotionEffectType.ABSORPTION.getId(), "Absorption"); + put(PotionEffectType.SATURATION.getId(), "Saturation"); + } + }; + + public static String getEffectName(PotionEffectType e) { + if (e == null) { + return "null"; + } + final String n = potionEffectNames.get(e.getId()); + return n == null ? e.getName() : n; + } +} diff --git a/src/main/java/com/songoda/core/library/compatibility/ParticleHandler.java b/src/main/java/com/songoda/core/library/compatibility/ParticleHandler.java new file mode 100644 index 00000000..19bcc0d6 --- /dev/null +++ b/src/main/java/com/songoda/core/library/compatibility/ParticleHandler.java @@ -0,0 +1,66 @@ +package com.songoda.core.library.compatibility; + +import org.bukkit.Color; +import org.bukkit.Effect; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.block.BlockFace; + +public class ParticleHandler { + + public static void redstoneParticles(Location location, int red, int green, int blue) { + redstoneParticles(location, red, green, blue, 1F, 1, 0); + } + + /** + * Spawn colored redstone particles + * + * @param location area to spawn the particle in + * @param red red value 0-255 + * @param green green value 0-255 + * @param blue blue value 0-255 + * @param size (1.13+) size of the particles + * @param count how many particles to spawn + * @param radius how far to spread out the particles from location + */ + public static void redstoneParticles(Location location, int red, int green, int blue, float size, int count, float radius) { + if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_13)) { + float xx = (float) (0 + (Math.random() * 1)); + float yy = (float) (0 + (Math.random() * 1)); + float zz = (float) (0 + (Math.random() * 1)); + location.getWorld().spawnParticle(Particle.REDSTONE, location, count, xx, yy, zz, 1, new Particle.DustOptions(Color.fromBGR(blue, green, red), size)); + } else if (ServerVersion.isServerVersionAtLeast(ServerVersion.V1_9)) { + for (int i = 0; i < count; i++) { + float xx = (float) (radius * (Math.random() - Math.random())); + float yy = (float) (radius * (Math.random() - Math.random())); + float zz = (float) (radius * (Math.random() - Math.random())); + Location at = location.clone().add(xx, yy, zz); + location.getWorld().spawnParticle(Particle.REDSTONE, at, 0, red / 255F, green / 255F, blue / 255F, size); // particle, location, count, red, green, blue, extra data + } + } else { + // WE NEED MAGIC! + for (int i = 0; i < count; i++) { + float xx = (float) (radius * (Math.random() - Math.random())); + float yy = (float) (radius * (Math.random() - Math.random())); + float zz = (float) (radius * (Math.random() - Math.random())); + Location at = location.clone().add(xx, yy, zz); + LegacyParticleEffects.createParticle(at, LegacyParticleEffects.Type.REDSTONE, + red / 255F, green / 255F, blue / 255F, 1F, 0, null); + } + } + } + + public static void bonemealSmoke(Location l) { + final org.bukkit.World w = l.getWorld(); + w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_EAST); + w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH); + w.playEffect(l, Effect.SMOKE, BlockFace.SOUTH_WEST); + w.playEffect(l, Effect.SMOKE, BlockFace.EAST); + w.playEffect(l, Effect.SMOKE, BlockFace.SELF); + w.playEffect(l, Effect.SMOKE, BlockFace.WEST); + w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_EAST); + w.playEffect(l, Effect.SMOKE, BlockFace.NORTH); + w.playEffect(l, Effect.SMOKE, BlockFace.NORTH_WEST); + } + +} diff --git a/src/main/java/com/songoda/core/library/economy/EconomyManager.java b/src/main/java/com/songoda/core/library/economy/EconomyManager.java index 82859a1a..eb3aa06b 100644 --- a/src/main/java/com/songoda/core/library/economy/EconomyManager.java +++ b/src/main/java/com/songoda/core/library/economy/EconomyManager.java @@ -27,9 +27,11 @@ public class EconomyManager { for (EconomyType type : EconomyType.values()) { if (pluginManager.isPluginEnabled(type.plugin)) { Economy econ = type.getInstance(); - registeredEconomies.put(type, econ); - if (defaultEcon == null) - defaultEcon = econ; + if(econ.isEnabled()) { + registeredEconomies.put(type, econ); + if (defaultEcon == null) + defaultEcon = econ; + } } } } diff --git a/src/main/java/com/songoda/core/library/economy/economies/Economy.java b/src/main/java/com/songoda/core/library/economy/economies/Economy.java index 8be4fac9..21a31b25 100644 --- a/src/main/java/com/songoda/core/library/economy/economies/Economy.java +++ b/src/main/java/com/songoda/core/library/economy/economies/Economy.java @@ -11,6 +11,12 @@ public interface Economy { */ String getName(); + /** + * Check to see if the economy plugin being used is active + * @return true if the plugin is loaded and active + */ + boolean isEnabled(); + /** * Check to see if a player has at least some balance available * diff --git a/src/main/java/com/songoda/core/library/economy/economies/PlayerPointsEconomy.java b/src/main/java/com/songoda/core/library/economy/economies/PlayerPointsEconomy.java index 538f5027..d8ed83bb 100644 --- a/src/main/java/com/songoda/core/library/economy/economies/PlayerPointsEconomy.java +++ b/src/main/java/com/songoda/core/library/economy/economies/PlayerPointsEconomy.java @@ -16,6 +16,11 @@ public class PlayerPointsEconomy implements Economy { return (int) Math.ceil(amount); } + @Override + public boolean isEnabled() { + return playerPoints.isEnabled(); + } + @Override public String getName() { return "PlayerPoints"; diff --git a/src/main/java/com/songoda/core/library/economy/economies/ReserveEconomy.java b/src/main/java/com/songoda/core/library/economy/economies/ReserveEconomy.java index 56c34424..12420d10 100644 --- a/src/main/java/com/songoda/core/library/economy/economies/ReserveEconomy.java +++ b/src/main/java/com/songoda/core/library/economy/economies/ReserveEconomy.java @@ -15,6 +15,11 @@ public class ReserveEconomy implements Economy { economyAPI = Reserve.instance().economy(); } + @Override + public boolean isEnabled() { + return Reserve.instance().isEnabled(); + } + @Override public String getName() { return "Reserve"; diff --git a/src/main/java/com/songoda/core/library/economy/economies/VaultEconomy.java b/src/main/java/com/songoda/core/library/economy/economies/VaultEconomy.java index 14fbe64b..e16dc793 100644 --- a/src/main/java/com/songoda/core/library/economy/economies/VaultEconomy.java +++ b/src/main/java/com/songoda/core/library/economy/economies/VaultEconomy.java @@ -2,14 +2,26 @@ package com.songoda.core.library.economy.economies; import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; +import org.bukkit.plugin.RegisteredServiceProvider; public class VaultEconomy implements Economy { private final net.milkbowl.vault.economy.Economy vault; public VaultEconomy() { - this.vault = Bukkit.getServicesManager(). - getRegistration(net.milkbowl.vault.economy.Economy.class).getProvider(); + // this returns null if we have Vault with no compatibe eco plugin + RegisteredServiceProvider v = Bukkit.getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class); + if(v != null) { + this.vault = v.getProvider(); + } else { + // whoopsie! + this.vault = null; + } + } + + @Override + public boolean isEnabled() { + return vault != null; } @Override @@ -19,16 +31,16 @@ public class VaultEconomy implements Economy { @Override public boolean hasBalance(OfflinePlayer player, double cost) { - return vault.has(player, cost); + return vault != null && vault.has(player, cost); } @Override public boolean withdrawBalance(OfflinePlayer player, double cost) { - return vault.withdrawPlayer(player, cost).transactionSuccess(); + return vault != null && vault.withdrawPlayer(player, cost).transactionSuccess(); } @Override public boolean deposit(OfflinePlayer player, double amount) { - return vault.depositPlayer(player, amount).transactionSuccess(); + return vault != null && vault.depositPlayer(player, amount).transactionSuccess(); } } diff --git a/src/main/java/com/songoda/core/library/hooks/hooks/WorldGuardFlagHandler.java b/src/main/java/com/songoda/core/library/hooks/hooks/WorldGuardFlagHandler.java index a8aa4f9b..410b77a2 100644 --- a/src/main/java/com/songoda/core/library/hooks/hooks/WorldGuardFlagHandler.java +++ b/src/main/java/com/songoda/core/library/hooks/hooks/WorldGuardFlagHandler.java @@ -33,7 +33,8 @@ public class WorldGuardFlagHandler { static Boolean wgPlugin = null; static Object worldGuardPlugin; - static boolean legacy = false; + static boolean legacy_v6 = false; + static boolean legacy_v5 = false; static boolean hooksInstalled = false; static Map flags = new HashMap(); @@ -47,15 +48,23 @@ public class WorldGuardFlagHandler { public static void addHook(String flag, boolean state) { if (wgPlugin == null && (wgPlugin = (worldGuardPlugin = Bukkit.getPluginManager().getPlugin("WorldGuard")) != null)) { try { - // if this class exists, we're on an older version + // if this class exists, we're on 6.0 Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry"); - legacy = true; + legacy_v6 = true; } catch (ClassNotFoundException ex) { } + if(!legacy_v6) { + try { + // if this class exists, we're on 5.x + Class.forName("com.sk89q.worldguard.protection.flags.DefaultFlag"); + legacy_v5 = true; + } catch (ClassNotFoundException ex) { + } + } } if (!wgPlugin) return; - if (legacy) { + if (legacy_v6 || legacy_v5) { addLegacyHook(flag, state); return; } @@ -109,11 +118,13 @@ public class WorldGuardFlagHandler { // and put the new list into place setStaticField(flagField, flagsNew); - // register this flag in the registry - Object flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry"); - Class simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry"); - Method registerSimpleFlagRegistry = simpleFlagRegistryClazz.getDeclaredMethod("register", Flag.class); - registerSimpleFlagRegistry.invoke(flagRegistry, wgFlag); + if(legacy_v6) { + // register this flag in the registry + Object flagRegistry = getPrivateField(worldGuardPlugin.getClass(), worldGuardPlugin, "flagRegistry"); + Class simpleFlagRegistryClazz = Class.forName("com.sk89q.worldguard.protection.flags.registry.SimpleFlagRegistry"); + Method registerSimpleFlagRegistry = simpleFlagRegistryClazz.getDeclaredMethod("register", Flag.class); + registerSimpleFlagRegistry.invoke(flagRegistry, wgFlag); + } // all good! flags.put(flag, wgFlag); @@ -153,11 +164,11 @@ public class WorldGuardFlagHandler { if (wgPlugin == null || !wgPlugin) return null; Object flagObj = flags.get(flag); // There's a different way to get this in the old version - if (legacy) + if (legacy_v6 || legacy_v5) return flagObj == null ? null : getBooleanFlagLegacy(l, flagObj); // for convinience, we can load a flag if we don't know it - if (flagObj == null && !legacy) + if (flagObj == null && !legacy_v6) flags.put(flag, flagObj = WorldGuard.getInstance().getFlagRegistry().get(flag)); // so, what's up? @@ -180,7 +191,7 @@ public class WorldGuardFlagHandler { if (wgPlugin == null || !wgPlugin) return null; Object flagObj = flags.get(flag); // There's a different way to get this in the old version - if (legacy) + if (legacy_v6 || legacy_v5) return flagObj == null ? null : getBooleanFlagLegacy(c, flagObj); // for convinience, we can load a flag if we don't know it @@ -207,6 +218,7 @@ public class WorldGuardFlagHandler { static Method legacy_getRegionManager = null; static Method legacy_getApplicableRegions_Region = null; static Method legacy_getApplicableRegions_Location = null; + static Method legacy5_applicableRegionSet_getFlag = null; static Constructor legacy_newProtectedCuboidRegion; static Class legacy_blockVectorClazz; static Constructor legacy_newblockVector; @@ -233,11 +245,22 @@ public class WorldGuardFlagHandler { return null; // now look for any intersecting regions - ApplicableRegionSet set = (ApplicableRegionSet) legacy_getApplicableRegions_Region.invoke(worldManager, l); + Object set = legacy_getApplicableRegions_Region.invoke(worldManager, l); // so what's the verdict? - State result = set.queryState((RegionAssociable) null, (StateFlag) flag); - if (result == null && set.size() == 0) + State result = null; + if(legacy_v6) { + set = ((ApplicableRegionSet) set).queryState((RegionAssociable) null, (StateFlag) flag); + } else { + // v5 has a different class signature for ApplicableRegionSet + // also doesn't have a "queryState" function + //getFlag(T flag) + if(legacy5_applicableRegionSet_getFlag == null) { + legacy5_applicableRegionSet_getFlag = Class.forName("com.sk89q.worldguard.protection.ApplicableRegionSet").getMethod("getFlag", Object.class); + } + result = (State) legacy5_applicableRegionSet_getFlag.invoke(set, flag); + } + if (result == null && set != null && ((Iterable) set).iterator().hasNext()) return null; return result == State.ALLOW; @@ -276,11 +299,22 @@ public class WorldGuardFlagHandler { legacy_newblockVector.newInstance((c.getX() << 4) + 15, 0, (c.getZ() << 4) + 15)); // now look for any intersecting regions - ApplicableRegionSet set = (ApplicableRegionSet) legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion); + Object set = legacy_getApplicableRegions_Region.invoke(worldManager, chunkRegion); // so what's the verdict? - State result = set.queryState((RegionAssociable) null, (StateFlag) flag); - if (result == null && set.size() == 0) + State result = null; + if(legacy_v6) { + set = ((ApplicableRegionSet) set).queryState((RegionAssociable) null, (StateFlag) flag); + } else { + // v5 has a different class signature for ApplicableRegionSet + // also doesn't have a "queryState" function + //getFlag(T flag) + if(legacy5_applicableRegionSet_getFlag == null) { + legacy5_applicableRegionSet_getFlag = Class.forName("com.sk89q.worldguard.protection.ApplicableRegionSet").getMethod("getFlag", Flag.class); + } + result = (State) legacy5_applicableRegionSet_getFlag.invoke(set, flag); + } + if (result == null && set != null && ((Iterable) set).iterator().hasNext()) return null; return result == State.ALLOW; diff --git a/src/main/java/com/songoda/core/library/locale/Locale.java b/src/main/java/com/songoda/core/library/locale/Locale.java index 17efac66..e9c66f9e 100644 --- a/src/main/java/com/songoda/core/library/locale/Locale.java +++ b/src/main/java/com/songoda/core/library/locale/Locale.java @@ -1,10 +1,17 @@ package com.songoda.core.library.locale; -import com.songoda.core.SongodaCore; -import com.songoda.core.modules.common.LocaleModule; import org.bukkit.plugin.java.JavaPlugin; -import java.io.*; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -220,11 +227,11 @@ public class Locale { try (BufferedReader reader = new BufferedReader(new FileReader(file))) { String line; for (int lineNumber = 0; (line = reader.readLine()) != null; lineNumber++) { - if (line.trim().isEmpty() || line.startsWith("#") /* Comment */) continue; + if ((line = line.trim()).isEmpty() || line.startsWith("#") /* Comment */) continue; Matcher matcher = NODE_PATTERN.matcher(line); if (!matcher.find()) { - System.err.println("Invalid locale syntax at (line=" + lineNumber + ")"); + System.err.println("Invalid locale syntax at (line=" + lineNumber + "): " + line); continue; } @@ -244,7 +251,7 @@ public class Locale { * @return applied message */ private Message supplyPrefix(Message message) { - return message.setPrefix(this.nodes.getOrDefault("general.nametag.prefix", "[Plugin]")); + return message.setPrefix(this.nodes.getOrDefault("general.nametag.prefix", "[" + plugin.getName() + "]")); } /** diff --git a/src/main/java/com/songoda/core/library/locale/Message.java b/src/main/java/com/songoda/core/library/locale/Message.java index 4aef25ab..073c453a 100644 --- a/src/main/java/com/songoda/core/library/locale/Message.java +++ b/src/main/java/com/songoda/core/library/locale/Message.java @@ -1,5 +1,6 @@ package com.songoda.core.library.locale; +import java.util.regex.Matcher; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -104,15 +105,16 @@ public class Message { } /** - * Replace the provided placeholder with the - * provided object + * Replace the provided placeholder with the provided object.
+ * Interchangeably Supports {@code %value%} and {@code {value}} * * @param placeholder the placeholder to replace * @param replacement the replacement object * @return the modified Message */ public Message processPlaceholder(String placeholder, Object replacement) { - this.message = message.replace("%" + placeholder + "%", replacement.toString()); + final String place = Matcher.quoteReplacement(placeholder); + this.message = message.replaceAll("%" + place + "%|\\{" + place +"\\}", Matcher.quoteReplacement(replacement.toString())); return this; } diff --git a/src/main/java/com/songoda/core/listeners/LoginListener.java b/src/main/java/com/songoda/core/listeners/LoginListener.java deleted file mode 100644 index af16e22e..00000000 --- a/src/main/java/com/songoda/core/listeners/LoginListener.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.songoda.core.listeners; - -import com.songoda.core.PluginInfo; -import com.songoda.core.SongodaCore; -import org.bukkit.Bukkit; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerLoginEvent; - -public class LoginListener implements Listener { - - private SongodaCore instance; - - public LoginListener(SongodaCore instance) { - this.instance = instance; - } - - @EventHandler - public void onLogin(PlayerLoginEvent event) { - if (!event.getPlayer().isOp()) return; - for (PluginInfo plugin : instance.getPlugins()) { - if (plugin.getNotification() != null) - Bukkit.getScheduler().scheduleSyncDelayedTask(plugin.getJavaPlugin(), () -> - event.getPlayer().sendMessage("[" + plugin.getJavaPlugin().getName() + "] " + plugin.getNotification()), 10L); - } - } -} diff --git a/src/main/java/com/songoda/core/modules/Module.java b/src/main/java/com/songoda/core/modules/Module.java deleted file mode 100644 index 2cfd3c25..00000000 --- a/src/main/java/com/songoda/core/modules/Module.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.songoda.core.modules; - -import com.songoda.core.PluginInfo; - -public interface Module { - - void run(PluginInfo plugin); - -} diff --git a/src/main/java/com/songoda/core/modules/common/LocaleModule.java b/src/main/java/com/songoda/core/modules/common/LocaleModule.java index e951eff5..550b4c3f 100644 --- a/src/main/java/com/songoda/core/modules/common/LocaleModule.java +++ b/src/main/java/com/songoda/core/modules/common/LocaleModule.java @@ -1,7 +1,7 @@ package com.songoda.core.modules.common; import com.songoda.core.library.locale.Locale; -import com.songoda.core.modules.Module; +import com.songoda.core.PluginInfoModule; import com.songoda.core.PluginInfo; import org.json.simple.JSONArray; import org.json.simple.JSONObject; @@ -10,7 +10,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; -public class LocaleModule implements Module { +public class LocaleModule implements PluginInfoModule { @Override public void run(PluginInfo plugin) {